From patchwork Sat Jan 21 03:03:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stafford Horne X-Patchwork-Id: 18975 Received: (qmail 12265 invoked by alias); 21 Jan 2017 03:04:50 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 12174 invoked by uid 89); 21 Jan 2017 03:04:49 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=cia, GROUP, Cover, BIG X-HELO: mail-pf0-f195.google.com Received: from mail-pf0-f195.google.com (HELO mail-pf0-f195.google.com) (209.85.192.195) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 21 Jan 2017 03:04:38 +0000 Received: by mail-pf0-f195.google.com with SMTP id f144so6441802pfa.2 for ; Fri, 20 Jan 2017 19:04:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=jHriBT5YOjmsO6qC/z7EG11TWUXQrWFcN0bnqY9JHSA=; b=ncSBoJYYtpWZaiaNwOxXf1UPF/Xnjl+6phkSCHT4p1FB4eYImmmbwFfXJNrhP/HX7w 3GUkkREJyNzIfAZhqT9WDWD4NpXMhSI1cFhbVx0qCdQinFo0Ppje0kstXZmm3gBlW8MB tzcjLZnK/OKFhYS3n7c8z6bKDTzdQKbtcsBzUFuO6wD+Abtfilj7lJuChnJv+bQ5xXz7 ivbvojYGcevEj+ISwo44BfiUjKGQb9pKDBiFs8LsDJno51B+7yLx0v93GfBLgxxjTl4/ nJY3lZeZZAiei6az1pdP77EU95sFZXt0l4HVaa3xxVX7zaXSXLunreGUyvjCaODMLk/u 9+6w== X-Gm-Message-State: AIkVDXJ5y1wtrtMH1fZYNR6bu1I1n8Qdj1dBhARZOpwOdylElGFoSYGoqMGKYA3OJ868lg== X-Received: by 10.98.35.207 with SMTP id q76mr20139996pfj.112.1484967876036; Fri, 20 Jan 2017 19:04:36 -0800 (PST) Received: from localhost (g149.219-103-224.ppp.wakwak.ne.jp. [219.103.224.149]) by smtp.gmail.com with ESMTPSA id e129sm1372328pfe.8.2017.01.20.19.04.34 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 20 Jan 2017 19:04:35 -0800 (PST) From: Stafford Horne To: gdb-patches@sourceware.org Cc: openrisc@lists.librecores.org, Stafford Horne Subject: [PATCH v2 4/6] sim: or1k: add or1k target to sim Date: Sat, 21 Jan 2017 12:03:53 +0900 Message-Id: <92c04bd768b66a48e03850af185e975d01605435.1484967575.git.shorne@gmail.com> In-Reply-To: References: In-Reply-To: References: X-IsSubscribed: yes sim/ChangeLog: 2017-01-20 Stafford Horne Peter Gavin * configure.tgt: Add or1k sim. * or1k/Makefile.in: New file. * or1k/arch.h: New file. * or1k/configure.ac: New file. * or1k/cpu.h: New file. * or1k/cpuall.h: New file. * or1k/decode.h: New file. * or1k/eng.h: New file. * or1k/mloop.in: New file. * or1k/or1k-sim.h: New file. * or1k/or1k.c: New file. * or1k/or1k.h: New file. * or1k/sim-if.c: New file. * or1k/sim-main.h: New file. * or1k/traps-linux.c: New file. * or1k/traps.c: New file. --- sim/configure.tgt | 4 + sim/or1k/Makefile.in | 232 ++++++++++++++++++++++++++++++++++++ sim/or1k/arch.h | 5 + sim/or1k/configure.ac | 41 +++++++ sim/or1k/cpu.h | 5 + sim/or1k/cpuall.h | 5 + sim/or1k/decode.h | 5 + sim/or1k/eng.h | 5 + sim/or1k/mloop.in | 244 +++++++++++++++++++++++++++++++++++++ sim/or1k/or1k-sim.h | 21 ++++ sim/or1k/or1k.c | 271 +++++++++++++++++++++++++++++++++++++++++ sim/or1k/or1k.h | 38 ++++++ sim/or1k/sim-if.c | 318 +++++++++++++++++++++++++++++++++++++++++++++++++ sim/or1k/sim-main.h | 78 ++++++++++++ sim/or1k/traps-linux.c | 32 +++++ sim/or1k/traps.c | 181 ++++++++++++++++++++++++++++ 16 files changed, 1485 insertions(+) create mode 100644 sim/or1k/Makefile.in create mode 100644 sim/or1k/arch.h create mode 100644 sim/or1k/configure.ac create mode 100644 sim/or1k/cpu.h create mode 100644 sim/or1k/cpuall.h create mode 100644 sim/or1k/decode.h create mode 100644 sim/or1k/eng.h create mode 100644 sim/or1k/mloop.in create mode 100644 sim/or1k/or1k-sim.h create mode 100644 sim/or1k/or1k.c create mode 100644 sim/or1k/or1k.h create mode 100644 sim/or1k/sim-if.c create mode 100644 sim/or1k/sim-main.h create mode 100644 sim/or1k/traps-linux.c create mode 100644 sim/or1k/traps.c diff --git a/sim/configure.tgt b/sim/configure.tgt index c958fb3..82b0e89 100644 --- a/sim/configure.tgt +++ b/sim/configure.tgt @@ -76,6 +76,10 @@ case "${target}" in msp430*-*-*) SIM_ARCH(msp430) ;; + or1k-*-* | or1knd-*-*) + SIM_ARCH(or1k) + sim_testsuite=yes + ;; rl78-*-*) SIM_ARCH(rl78) ;; diff --git a/sim/or1k/Makefile.in b/sim/or1k/Makefile.in new file mode 100644 index 0000000..df95012 --- /dev/null +++ b/sim/or1k/Makefile.in @@ -0,0 +1,232 @@ +# Makefile template for Configure for the or1k simulator +# Copyright (C) 1996-2000, 2003-2004, 2007-2012 Free Software +# Foundation, Inc. +# Contributed by Cygnus Support. +# +# This file is part of GDB, the GNU debugger. +# +# 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 . + +## COMMON_PRE_CONFIG_FRAG + +OR1K32_OBJS = \ + or1k32.o \ + arch32.o \ + cpu32.o \ + decode32.o \ + model32.o \ + sem32.o \ + mloop32.o \ + sim-if32.o + +OR1K64_OBJS = \ + or1k64.o \ + arch64.o \ + cpu64.o \ + decode64.o \ + model64.o \ + sem64.o \ + mloop64.o \ + sim-if64.o + +TRAPS_OBJ = @traps_obj@ + +SIM_OBJS = \ + $(SIM_NEW_COMMON_OBJS) \ + sim-cpu.o \ + sim-hload.o \ + sim-hrw.o \ + sim-reg.o \ + cgen-utils.o \ + cgen-trace.o \ + cgen-scache.o \ + cgen-run.o \ + sim-reason.o \ + sim-engine.o \ + sim-model.o \ + sim-stop.o \ + $(TRAPS_OBJ) +ifneq (@want_or1k64@,true) +SIM_OBJS += $(OR1K32_OBJS) +else +SIM_OBJS += $(OR1K64_OBJS) +endif + +# Extra headers included by sim-main.h. +SIM_EXTRA_DEPS = \ + $(CGEN_INCLUDE_DEPS) \ + or1k-sim.h \ + $(srcdir)/../../opcodes/or1k-desc.h \ + arch32.h \ + cpuall32.h \ + decode32.h \ + arch64.h \ + cpuall64.h \ + decode64.h + +SIM_EXTRA_CFLAGS = @sim_extra_cflags@ +ifeq (@want_or1k64@,true) +SIM_EXTRA_CFLAGS += -DWANT_OR1K64 +endif +ifeq (@want_or1k_nodelay@,true) +SIM_EXTRA_CFLAGS += -DWANT_OR1K_NODELAY +endif + +SIM_EXTRA_LIBS = -lm + +SIM_RUN_OBJS = nrun.o +SIM_EXTRA_CLEAN = + +## COMMON_POST_CONFIG_FRAG + +arch = or1k + +# or1k32bf + +OR1K32BF_INCLUDE_DEPS = \ + $(CGEN_MAIN_CPU_DEPS) \ + cpu32.h \ + decode32.h \ + eng32.h + +mloop32.c eng32.h: stamp-mloop32 ; @true +stamp-mloop32: $(srcdir)/../common/genmloop.sh mloop.in Makefile + $(SHELL) $(srccom)/genmloop.sh -shell $(SHELL) \ + -mono -fast -pbb -switch sem32-switch.c \ + -cpu or1k32bf -infile $(srcdir)/mloop.in + $(SHELL) $(srcroot)/move-if-change eng.hin eng32.h + $(SHELL) $(srcroot)/move-if-change mloop.cin mloop32.c + touch stamp-mloop32 +mloop32.o: mloop32.c sem32-switch.c $(OR1K32BF_INCLUDE_DEPS) +or1k32.o: or1k.c $(OR1K32BF_INCLUDE_DEPS) + $(COMPILE) $< + $(POSTCOMPILE) +arch32.o: arch32.c $(SIM_MAIN_DEPS) +cpu32.o: cpu32.c $(OR1K32BF_INCLUDE_DEPS) +decode32.o: decode32.c $(OR1K32BF_INCLUDE_DEPS) +sem32.o: sem32.c $(OR1K32BF_INCLUDE_DEPS) +sem32-switch.o: sem32-switch.c $(OR1K32BF_INCLUDE_DEPS) +model32.o: model32.c $(OR1K32BF_INCLUDE_DEPS) + +sim-if32.o: sim-if.c $(SIM_MAIN_DEPS) $(srcdir)/../common/sim-core.h eng32.h + $(COMPILE) $< + $(POSTCOMPILE) + +traps32.o: traps.c $(SIM_MAIN_DEPS) eng32.h + $(COMPILE) $< + $(POSTCOMPILE) +traps32-linux.o: traps-linux.c $(SIM_MAIN_DEPS) eng32.h + $(COMPILE) $< + $(POSTCOMPILE) + + +# or1k64bf + +OR1K64BF_INCLUDE_DEPS = \ + $(CGEN_MAIN_CPU_DEPS) \ + cpu64.h \ + decode64.h \ + eng64.h + +mloop64.c eng64.h: stamp-mloop64 ; @true +stamp-mloop64: $(srcdir)/../common/genmloop.sh mloop.in Makefile + $(SHELL) $(srccom)/genmloop.sh -shell $(SHELL) \ + -mono -fast -pbb -switch sem32-switch.c \ + -cpu or1k64bf -infile $(srcdir)/mloop.in + $(SHELL) $(srcroot)/move-if-change eng64.hin eng64.h + $(SHELL) $(srcroot)/move-if-change mloop64.cin mloop64.c + touch stamp-mloop64 +mloop64.o: mloop64.c sem64.c $(OR1K64BF_INCLUDE_DEPS) +or1k64.o: or1k.c $(OR1K64BF_INCLUDE_DEPS) + $(COMPILE) $< + $(POSTCOMPILE) +arch64.o: arch64.c $(SIM_MAIN_DEPS) +cpu64.o: cpu64.c $(OR1K64BF_INCLUDE_DEPS) +decode64.o: decode64.c $(OR1K64BF_INCLUDE_DEPS) +sem64.o: sem64.c $(OR1K64BF_INCLUDE_DEPS) +sem64-switch.o: sem64-switch.c $(OR1K64BF_INCLUDE_DEPS) +model64.o: model64.c $(OR1K64BF_INCLUDE_DEPS) + +sim-if64.o: sim-if.c $(SIM_MAIN_DEPS) $(srcdir)/../common/sim-core.h eng64.h + $(COMPILE) $< + $(POSTCOMPILE) + +traps64.o: traps.c $(SIM_MAIN_DEPS) eng64.h + $(COMPILE) $< + $(POSTCOMPILE) +traps64-linux.o: traps-linux.c $(SIM_MAIN_DEPS) eng64.h + $(COMPILE) $< + $(POSTCOMPILE) + + +# cgen support, enable with --enable-cgen-maint +CGEN_MAINT = ; @true +# The following line is commented in or out depending upon --enable-cgen-maint. +@CGEN_MAINT@CGEN_MAINT = + +# NOTE: Generated source files are specified as full paths, +# e.g. $(srcdir)/arch.c, because make may decide the files live +# in objdir otherwise. + +OR1K_CGEN_DEPS = \ + $(CPU_DIR)/or1k.cpu \ + $(CPU_DIR)/or1k.opc \ + $(CPU_DIR)/or1kcommon.cpu \ + $(CPU_DIR)/or1korbis.cpu \ + $(CPU_DIR)/or1korfpx.cpu \ + Makefile + +stamp-arch32: $(CGEN_READ_SCM) $(CGEN_ARCH_SCM) $(OR1K_CGEN_DEPS) + $(MAKE) cgen-arch $(CGEN_FLAGS_TO_PASS) \ + mach=or32,or32nd \ + SUFFIX=32 \ + archfile=$(CPU_DIR)/or1k.cpu \ + FLAGS="with-scache" + touch $@ +$(srcdir)/arch32.h $(srcdir)/arch32.c $(srcdir)/cpuall32.h: $(CGEN_MAINT) stamp-arch32 + @true + +stamp-arch64: $(CGEN_READ_SCM) $(CGEN_ARCH_SCM) $(OR1K_CGEN_DEPS) + $(MAKE) cgen-arch $(CGEN_FLAGS_TO_PASS) \ + mach=or64,or64nd \ + SUFFIX=64 \ + archfile=$(CPU_DIR)/or1k.cpu \ + FLAGS="with-scache" + touch $@ +$(srcdir)/arch64.h $(srcdir)/arch64.c $(srcdir)/cpuall64.h: $(CGEN_MAINT) stamp-arch64 + @true + +stamp-cpu32: $(CGEN_READ_SCM) $(CGEN_CPU_SCM) $(OR1K_CGEN_DEPS) + $(MAKE) cgen-cpu-decode $(CGEN_FLAGS_TO_PASS) \ + cpu=or1k32bf \ + mach=or32,or32nd \ + SUFFIX=32 \ + archfile=$(CPU_DIR)/or1k.cpu \ + FLAGS="with-scache" \ + EXTRAFILES="$(CGEN_CPU_SEM) $(CGEN_CPU_SEMSW)" + touch $@ +$(srcdir)/cpu32.h $(srcdir)/cpu32.c $(srcdir)/model32.c $(srcdir)/sem32.c $(srcdir)/sem32-switch.c $(srcdir)/decode32.c $(srcdir)/decode32.h: $(CGEN_MAINT) stamp-cpu32 + @true + +stamp-cpu64: $(CGEN_READ_SCM) $(CGEN_CPU_SCM) $(OR1K_CGEN_DEPS) + $(MAKE) cgen-cpu-decode $(CGEN_FLAGS_TO_PASS) \ + cpu=or1k64bf \ + mach=or64,or64nd \ + SUFFIX=64 \ + archfile=$(CPU_DIR)/or1k.cpu \ + FLAGS="with-scache" \ + EXTRAFILES="$(CGEN_CPU_SEM) $(CGEN_CPU_SEMSW)" + touch $@ +$(srcdir)/cpu64.h $(srcdir)/cpu64.c $(srcdir)/model64.c $(srcdir)/sem64.c $(srcdir)/sem64-switch.c $(srcdir)/decode64.c $(srcdir)/decode64.h: $(CGEN_MAINT) stamp-cpu64 + @true diff --git a/sim/or1k/arch.h b/sim/or1k/arch.h new file mode 100644 index 0000000..88202a2 --- /dev/null +++ b/sim/or1k/arch.h @@ -0,0 +1,5 @@ +#ifndef WANT_OR1K64 +#include "arch32.h" +#else +#include "arch64.h" +#endif diff --git a/sim/or1k/configure.ac b/sim/or1k/configure.ac new file mode 100644 index 0000000..e0b5a90 --- /dev/null +++ b/sim/or1k/configure.ac @@ -0,0 +1,41 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ(2.64)dnl +AC_INIT(Makefile.in) +sinclude(../common/acinclude.m4) + + case "${target_alias}" in + or1k-linux*|or1knd-linux*) + traps_obj=traps32-linux.o + ;; + or1k-*|or1knd-*) + traps_obj=traps32.o + ;; + esac + + case "${target_alias}" in + or1knd-*) + want_or1k_nodelay=true + default_model=or1200nd + ;; + *) + default_model=or1200 + ;; + esac + +SIM_AC_COMMON + +SIM_AC_OPTION_ENDIAN(BIG) +SIM_AC_OPTION_ALIGNMENT(STRICT_ALIGNMENT) +SIM_AC_OPTION_BITSIZE([32], [31], [32]) +SIM_AC_OPTION_SCACHE(16384) +SIM_AC_OPTION_DEFAULT_MODEL([$default_model]) +SIM_AC_OPTION_ENVIRONMENT +SIM_AC_OPTION_INLINE() +SIM_AC_OPTION_CGEN_MAINT + +AC_SUBST(traps_obj) +AC_SUBST(sim_extra_cflags) +AC_SUBST(want_or1k64) +AC_SUBST(want_or1k_nodelay) + +SIM_AC_OUTPUT diff --git a/sim/or1k/cpu.h b/sim/or1k/cpu.h new file mode 100644 index 0000000..1f2a5f3 --- /dev/null +++ b/sim/or1k/cpu.h @@ -0,0 +1,5 @@ +#ifndef WANT_OR1K64 +#include "cpu32.h" +#else +#include "cpu64.h" +#endif diff --git a/sim/or1k/cpuall.h b/sim/or1k/cpuall.h new file mode 100644 index 0000000..be6f87b --- /dev/null +++ b/sim/or1k/cpuall.h @@ -0,0 +1,5 @@ +#ifndef WANT_OR1K64 +#include "cpuall32.h" +#else +#include "cpuall64.h" +#endif diff --git a/sim/or1k/decode.h b/sim/or1k/decode.h new file mode 100644 index 0000000..fe96fbb --- /dev/null +++ b/sim/or1k/decode.h @@ -0,0 +1,5 @@ +#ifndef WANT_OR1K64 +#include "decode32.h" +#else +#include "decode64.h" +#endif diff --git a/sim/or1k/eng.h b/sim/or1k/eng.h new file mode 100644 index 0000000..a46cf86 --- /dev/null +++ b/sim/or1k/eng.h @@ -0,0 +1,5 @@ +#ifndef WANT_OR1K64 +#include "eng32.h" +#else +#include "eng64.h" +#endif diff --git a/sim/or1k/mloop.in b/sim/or1k/mloop.in new file mode 100644 index 0000000..8310033 --- /dev/null +++ b/sim/or1k/mloop.in @@ -0,0 +1,244 @@ +# Simulator main loop for or1k. -*- C -*- +# +# Copyright (C) 1996-1998, 2007-2012 Free Software Foundation, Inc. +# +# This file is part of the GNU 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 . + +# Syntax: +# /bin/sh mainloop.in command +# +# Command is one of: +# +# init +# support +# extract-{simple,scache,pbb} +# {full,fast}-exec-{simple,scache,pbb} +# +# A target need only provide a "full" version of one of simple,scache,pbb. +# If the target wants it can also provide a fast version of same, or if +# the slow (full featured) version is `simple', then the fast version can be +# one of scache/pbb. +# A target can't provide more than this. +# However for illustration's sake this file provides examples of all. + +# ??? After a few more ports are done, revisit. +# Will eventually need to machine generate a lot of this. + +case "x$1" in + +xsupport) + +cat <argbuf.idesc); + + if (fast_p) + { +#if ! WITH_SEM_SWITCH_FAST +#if WITH_SCACHE + vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc); +#else + vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf); +#endif +#else + abort (); +#endif /* WITH_SEM_SWITCH_FAST */ + } + else + { +#if ! WITH_SEM_SWITCH_FULL + ARGBUF *abuf = &sc->argbuf; + const IDESC *idesc = abuf->idesc; + const CGEN_INSN *idata = idesc->idata; +#if WITH_SCACHE_PBB + int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL); +#else + int virtual_p = 0; +#endif + + if (! virtual_p) + { + /* FIXME: call x-before */ + if (ARGBUF_PROFILE_P (abuf)) + PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num); + /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (abuf)) + @cpu@_model_insn_before (current_cpu, 1 /*first_p*/); + CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1); + CGEN_TRACE_INSN (current_cpu, idata, + (const struct argbuf *) abuf, abuf->addr); + } +#if WITH_SCACHE + vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc); +#else + vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf); +#endif + if (! virtual_p) + { + /* FIXME: call x-after */ + if (PROFILE_MODEL_P (current_cpu) + && ARGBUF_PROFILE_P (abuf)) + { + int cycles; + + cycles = (*idesc->timing->model_fn) (current_cpu, sc); + @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles); + } + CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1); + } +#else + abort (); +#endif /* WITH_SEM_SWITCH_FULL */ + } + + @cpu@_insn_after (current_cpu, vpc, sc->argbuf.idesc); + + return vpc; +} + +EOF + +;; + +xinit) + +# Nothing needed. + +;; + +xextract-simple | xextract-scache) + +cat < 0) { + + USI insn = GETIMEMUSI (current_cpu, pc); + + idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); + + SEM_SKIP_COMPILE (current_cpu, sc, 1); + + ++sc; + --max_insns; + ++icount; + pc += 4; + + if (CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_FORCED_CTI)) + { + + SET_CTI_VPC (sc - 1); + + break; + + } + else if (CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI)) + { + + /* handle delay slot */ + SET_CTI_VPC (sc - 1); + + insn = GETIMEMUSI (current_cpu, pc); + + idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P); + + ++sc; + --max_insns; + ++icount; + pc += 4; + + break; + } + } + + SET_INSN_COUNT (icount); + +} +EOF + +;; + +xfull-exec-* | xfast-exec-*) + +# Inputs: current_cpu, vpc, FAST_P +# Outputs: vpc +# vpc is the virtual program counter. + +cat <&2 + exit 1 + ;; + +esac diff --git a/sim/or1k/or1k-sim.h b/sim/or1k/or1k-sim.h new file mode 100644 index 0000000..3a256ce --- /dev/null +++ b/sim/or1k/or1k-sim.h @@ -0,0 +1,21 @@ +#ifndef OR1K_SIM_H +#define OR1K_SIM_H + +#include "symcat.h" + +/* GDB register numbers. */ +#define PPC_REGNUM 32 +#define PC_REGNUM 33 +#define SR_REGNUM 34 + +/* Misc. profile data. */ +typedef struct { +} OR1K_MISC_PROFILE; + +#define GETTWI XCONCAT2(GETT,WI) +#define SETTWI XCONCAT2(SETT,WI) + +#define EXIT_ERROR 1 +#define EXIT_UNSPECIFIED 2 + +#endif /* OR1K_SIM_H */ diff --git a/sim/or1k/or1k.c b/sim/or1k/or1k.c new file mode 100644 index 0000000..eeaf1b2 --- /dev/null +++ b/sim/or1k/or1k.c @@ -0,0 +1,271 @@ +#ifndef WANT_OR1K64 +#define WANT_CPU or1k32bf +#define WANT_CPU_OR1K32BF +#else +#define WANT_CPU or1k64bf +#define WANT_CPU_OR1K64BF +#endif + +#include "sim-main.h" +#include "symcat.h" +#include "cgen-ops.h" +#include "cgen-mem.h" +#include "cpuall.h" + +#include + +int XCONCAT2(WANT_CPU,_fetch_register) (sim_cpu *current_cpu, int rn, unsigned char *buf, int len) +{ + if (rn < 32) + SETTWI (buf, XCONCAT2(WANT_CPU,_h_gpr_get) (current_cpu, rn)); + else + switch (rn) + { + case PPC_REGNUM : + SETTWI (buf, XCONCAT2(WANT_CPU,_h_sys_ppc_get) (current_cpu)); + break; + case PC_REGNUM : + SETTWI (buf, XCONCAT2(WANT_CPU,_h_pc_get) (current_cpu)); + break; + case SR_REGNUM : + SETTWI (buf, XCONCAT2(WANT_CPU,_h_sys_sr_get) (current_cpu)); + break; + default : + return 0; + } + return sizeof(WI); /* WI from arch.h */ +} + +int XCONCAT2(WANT_CPU,_store_register) (sim_cpu *current_cpu, int rn, unsigned char *buf, int len) +{ + if (rn < 32) + XCONCAT2(WANT_CPU,_h_gpr_set) (current_cpu, rn, GETTWI (buf)); + else + switch (rn) + { + case PPC_REGNUM : + XCONCAT2(WANT_CPU,_h_sys_ppc_set) (current_cpu, GETTWI (buf)); + break; + case PC_REGNUM : + XCONCAT2(WANT_CPU,_h_pc_set) (current_cpu, GETTWI (buf)); + break; + case SR_REGNUM : + XCONCAT2(WANT_CPU,_h_sys_sr_set) (current_cpu, GETTWI (buf)); + break; + default : + return 0; + } + return sizeof(WI); /* WI from arch.h */ +} + +#ifdef WANT_CPU_OR1K32BF +int or1k32bf_model_or1200_u_exec (sim_cpu * UNUSED current_cpu, const IDESC * UNUSED idesc, int unit_num, int referenced) +{ + return -1; +} + +int or1k32bf_model_or1200nd_u_exec (sim_cpu * UNUSED current_cpu, const IDESC * UNUSED idesc, int unit_num, int referenced) +{ + return -1; +} + +void or1k32bf_model_insn_before (sim_cpu * UNUSED current_cpu, int UNUSED first_p) +{ +} + +void or1k32bf_model_insn_after (sim_cpu * UNUSED current_cpu, int UNUSED last_p, int UNUSED cycles) +{ +} + +USI or1k32bf_h_spr_get_raw (sim_cpu *current_cpu, USI addr) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + SIM_ASSERT(addr < NUM_SPR); + return current_cpu->spr[addr]; +} + +void or1k32bf_h_spr_set_raw (sim_cpu *current_cpu, USI addr, USI val) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + SIM_ASSERT(addr < NUM_SPR); + current_cpu->spr[addr] = val; +} + +USI or1k32bf_h_spr_field_get_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + SIM_ASSERT(addr < NUM_SPR); + return LSEXTRACTED(current_cpu->spr[addr], msb, lsb); +} + +void or1k32bf_h_spr_field_set_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb, USI val) +{ + current_cpu->spr[addr] &= ~LSMASK32(msb, lsb); + current_cpu->spr[addr] |= LSINSERTED(val, msb, lsb); +} + +void or1k32bf_cpu_init (SIM_DESC sd, sim_cpu *current_cpu) +{ +#define CHECK_SPR_FIELD(GROUP, INDEX, FIELD, test) \ + do { \ + USI field = GET_H_##SYS##_##INDEX##_##FIELD (); \ + if (!(test)) { \ + sim_io_eprintf(sd, "WARNING: unsupported %s field in %s register: 0x%x\n", \ + #FIELD, #INDEX, field); \ + } \ + } while (0) + + current_cpu->next_delay_slot = 0; + current_cpu->delay_slot = 0; + + CHECK_SPR_FIELD(SYS,UPR,UP, field == 1); + CHECK_SPR_FIELD(SYS,UPR,DCP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,ICP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,DMP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,MP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,IMP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,DUP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,PCUP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,PICP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,PMP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,TTP, field == 0); + CHECK_SPR_FIELD(SYS,UPR,CUP, field == 0); + + CHECK_SPR_FIELD(SYS,CPUCFGR,NSGR, field == 0); + CHECK_SPR_FIELD(SYS,CPUCFGR,CGF, field == 0); + CHECK_SPR_FIELD(SYS,CPUCFGR,OB32S, field == 1); + CHECK_SPR_FIELD(SYS,CPUCFGR,OB64S, field == 0); + CHECK_SPR_FIELD(SYS,CPUCFGR,OF64S, field == 0); + CHECK_SPR_FIELD(SYS,CPUCFGR,OV64S, field == 0); + +#undef CHECK_SPR_FIELD + + SET_H_SYS_UPR_UP(1); + + SET_H_SYS_SR(SPR_FIELD_MASK_SYS_SR_SM | + SPR_FIELD_MASK_SYS_SR_FO + ); + + SET_H_SYS_FPCSR(0); +} + +void or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, IDESC *idesc) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + current_cpu->delay_slot = current_cpu->next_delay_slot; + current_cpu->next_delay_slot = 0; + + if (current_cpu->delay_slot && + CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_NOT_IN_DELAY_SLOT)) { + USI pc; +#ifdef WITH_SCACHE + pc = vpc->argbuf.addr; +#else + pc = vpc; +#endif + sim_io_error (sd, "invalid instruction in a delay slot at PC 0x%08x", pc); + } + +} + +void or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, IDESC *idesc) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + USI ppc; + +#ifdef WITH_SCACHE + ppc = vpc->argbuf.addr; +#else + ppc = vpc; +#endif + + SET_H_SYS_PPC (ppc); + + if (!GET_H_SYS_CPUCFGR_ND () && + CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI)) { + SIM_ASSERT (!current_cpu->delay_slot); + current_cpu->next_delay_slot = 1; + } +} + +void or1k32bf_nop (sim_cpu *current_cpu, USI uimm16) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + switch (uimm16) { + + case NOP_NOP: + break; + + case NOP_EXIT: + sim_io_printf (CPU_STATE(current_cpu), "exit(%d)\n", GET_H_GPR(3)); + /* fall through */ + case NOP_EXIT_SILENT: + sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu), sim_exited, GET_H_GPR (3)); + break; + + case NOP_REPORT: + sim_io_printf (CPU_STATE(current_cpu), "report(0x%08x);\n", GET_H_GPR(3)); + break; + + case NOP_PUTC: + sim_io_printf (CPU_STATE(current_cpu), "%c", (char)(GET_H_GPR(3) & 0xff)); + break; + + default: + sim_io_eprintf(sd, "WARNING: l.nop with unsupported code 0x%08x\n", uimm16); + break; + } + +} + +USI or1k32bf_make_load_store_addr (sim_cpu *current_cpu, USI base, SI offset, int size) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + USI addr = base + offset; + + if (GET_H_SYS_SR_LEE ()) { + switch (size) { + + case 4: + break; + + case 2: + addr ^= 0x2; + + case 1: + addr ^= 0x3; + + default: + SIM_ASSERT (0); + return 0; + } + } + + return addr; +} + +USI or1k32bf_ff1 (sim_cpu *current_cpu, USI val) +{ + USI bit; + USI ret; + for (bit = 1, ret = 1; bit; bit <<= 1, ret++) { + if (val & bit) + return ret; + } + return 0; +} + +USI or1k32bf_fl1 (sim_cpu *current_cpu, USI val) +{ + USI bit; + USI ret; + for (bit = 1 << 31, ret = 32; bit; bit >>= 1, ret--) { + if (val & bit) + return ret; + } + return 0; +} +#endif diff --git a/sim/or1k/or1k.h b/sim/or1k/or1k.h new file mode 100644 index 0000000..e71a845 --- /dev/null +++ b/sim/or1k/or1k.h @@ -0,0 +1,38 @@ +#ifndef OR1K_H +#define OR1K_H + +#define NOP_NOP 0x0 +#define NOP_EXIT 0x1 +#define NOP_REPORT 0x2 +#define NOP_PUTC 0x4 +#define NOP_CNT_RESET 0x5 +#define NOP_GET_TICKS 0x6 +#define NOP_GET_PS 0x7 +#define NOP_TRACE_ON 0x8 +#define NOP_TRACE_OFF 0x9 +#define NOP_RANDOM 0xa +#define NOP_OR1KSIM 0xb +#define NOP_EXIT_SILENT 0xc + +#define NUM_SPR 0x20000 +#define SPR_GROUP_SHIFT 11 +#define SPR_GROUP_FIRST(group) (((UWI) SPR_GROUP_##group) << SPR_GROUP_SHIFT) +#define SPR_GROUP_LAST(group) (SPR_GROUP_FIRST | (((UWI) 1 << SPR_GROUP_SHIFT) - 1)) +#define SPR_ADDR(group,index) (SPR_GROUP_FIRST(group) | ((UWI) SPR_INDEX_##group##_##index)) +#define SPR_ADDR_GROUP(addr) (((UWI) (addr)) >> SPR_GROUP_SHIFT) +#define SPR_INDEX_MASK (~(~((UWI) 0) << SPR_GROUP_SHIFT)) +#define SPR_ADDR_INDEX(addr) (((UWI) (addr)) && SPR_INDEX_MASK) +#define SPR_FIELD(group,index,field,val) ((SPR_FIELD_MASK_##group##_##index##_##field & (val)) >> SPR_FIELD_LSB_##group##_##index##_##field) + +#ifdef WANT_CPU_OR1K32BF +void or1k32bf_cpu_init (SIM_DESC sd, sim_cpu *current_cpu); +void or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, IDESC *idesc); +void or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, IDESC *idesc); +void or1k32bf_exception (sim_cpu *current_cpu, USI pc, USI exnum); +void or1k32bf_rfe (sim_cpu *current_cpu); +void or1k32bf_nop (sim_cpu *current_cpu, USI uimm16); +USI or1k32bf_mfspr (sim_cpu *current_cpu, USI addr); +void or1k32bf_mtspr (sim_cpu *current_cpu, USI addr, USI val); +#endif + +#endif diff --git a/sim/or1k/sim-if.c b/sim/or1k/sim-if.c new file mode 100644 index 0000000..7749cff --- /dev/null +++ b/sim/or1k/sim-if.c @@ -0,0 +1,318 @@ +/* Main simulator entry points specific to the OR1K. + Copyright (C) 1996-1999, 2003, 2007-2012 Free Software Foundation, + Inc. + Contributed by Cygnus Support. + + This file is part of GDB, the GNU debugger. + + 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 WANT_OR1K64 +#define WANT_CPU or1k32bf +#define WANT_CPU_OR1K32BF +#else +#define WANT_CPU or1k64bf +#define WANT_CPU_OR1K64BF +#endif + +#include "sim-main.h" +#include "sim-options.h" +#include "libiberty.h" +#include "bfd.h" + +#ifdef HAVE_STRING_H +#include +#else +#ifdef HAVE_STRINGS_H +#include +#endif +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +static void free_state (SIM_DESC); + +/* Records simulator descriptor so utilities like or1k_dump_regs can be + called from gdb. */ +SIM_DESC current_state; + +/* Cover function of sim_state_free to free the cpu buffers as well. */ + +static void +free_state (SIM_DESC sd) +{ + if (STATE_MODULES (sd) != NULL) + sim_module_uninstall (sd); + sim_cpu_free_all (sd); + sim_state_free (sd); +} + +static const USI or1k_default_vr = 0x0; +static const USI or1k_default_upr = 0x0 + | SPR_FIELD_MASK_SYS_UPR_UP + ; +static const USI or1k_default_cpucfgr = 0x0 +#ifdef WANT_CPU_OR1K32BF + | SPR_FIELD_MASK_SYS_CPUCFGR_OB32S + | SPR_FIELD_MASK_SYS_CPUCFGR_OF32S +#endif +#ifdef WANT_CPU_OR1K64BF + | SPR_FIELD_MASK_SYS_CPUCFGR_OB64S + | SPR_FIELD_MASK_SYS_CPUCFGR_OF64S +#endif +#ifdef WANT_OR1K_NODELAY + | SPR_FIELD_MASK_SYS_CPUCFGR_ND +#endif + ; + +static UWI or1k_upr; +static UWI or1k_vr; +static UWI or1k_cpucfgr; + +enum { + OPTION_OR1K_VR, + OPTION_OR1K_UPR, + OPTION_OR1K_CPUCFGR = OPTION_START, +}; + +DECLARE_OPTION_HANDLER(or1k_option_handler); + +static const OPTION or1k_options[] = { + { {"or1k-cpucfgr", required_argument, NULL, OPTION_OR1K_CPUCFGR }, + '\0', "INTEGER|default", "Set simulator CPUCFGR value", + or1k_option_handler }, + { {"or1k-vr", required_argument, NULL, OPTION_OR1K_VR }, + '\0', "INTEGER|default", "Set simulator VR value", + or1k_option_handler }, + { {"or1k-upr", required_argument, NULL, OPTION_OR1K_VR }, + '\0', "INTEGER|default", "Set simulator UPR value", + or1k_option_handler }, + { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } +}; + +SIM_RC +or1k_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, + char *arg, int is_command) +{ + + switch (opt) { + + case OPTION_OR1K_VR: + if (strcmp("default", arg) == 0) { + or1k_vr = or1k_default_vr; + } else { + unsigned long long n; + char *endptr; + n = strtoull (arg, &endptr, 0); + if (*arg != '\0' && + *endptr == '\0') { + or1k_vr = n; + } else { + sim_io_eprintf (sd, "invalid argument to option --or1k-vr: `%s'\n", arg); + return SIM_RC_FAIL; + } + } + break; + + case OPTION_OR1K_UPR: + if (strcmp("default", arg) == 0) { + or1k_upr = or1k_default_upr; + } else { + unsigned long long n; + char *endptr; + n = strtoull (arg, &endptr, 0); + if (*arg != '\0' && + *endptr == '\0') { + or1k_upr = n; + } else { + sim_io_eprintf (sd, "invalid argument to option --or1k-upr: `%s'\n", arg); + return SIM_RC_FAIL; + } + } + break; + + case OPTION_OR1K_CPUCFGR: + if (strcmp("default", arg) == 0) { + or1k_cpucfgr = or1k_default_cpucfgr; + } else { + unsigned long long n; + char *endptr; + n = strtoull (arg, &endptr, 0); + if (*arg != '\0' && + *endptr == '\0') { + or1k_cpucfgr = n; + } else { + sim_io_eprintf (sd, "invalid argument to option --or1k-cpucfgr: `%s'\n", arg); + return SIM_RC_FAIL; + } + } + break; + + default: + abort (); + } + +} + + +/* Create an instance of the simulator. */ + +SIM_DESC +sim_open (kind, callback, abfd, argv) + SIM_OPEN_KIND kind; + host_callback *callback; + struct bfd *abfd; + char * const *argv; +{ + SIM_DESC sd = sim_state_alloc (kind, callback); + char c; + int i; + + /* The cpu data is kept in a separately allocated chunk of memory. */ + if (sim_cpu_alloc_all (sd, 1, cgen_cpu_max_extra_bytes ()) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + +#ifdef HAVE_DV_SOCKSER /* FIXME: was done differently before */ + if (dv_sockser_install (sd) != SIM_RC_OK) + { + free_state (sd); + return 0; + } +#endif + + /* These options override any module options. + Obviously ambiguity should be avoided, however the caller may wish to + augment the meaning of an option. */ + or1k_upr = or1k_default_upr; + or1k_vr = or1k_default_vr; + or1k_cpucfgr = or1k_default_cpucfgr; + sim_add_option_table (sd, NULL, or1k_options); + + /* getopt will print the error message so we just have to exit if this fails. + FIXME: Hmmm... in the case of gdb we need getopt to call + print_filtered. */ + if (sim_parse_args (sd, argv) != SIM_RC_OK) + { + free_state (sd); + return 0; + } + + /* Allocate core managed memory if none specified by user. + Use address 4 here in case the user wanted address 0 unmapped. */ + if (sim_core_read_buffer (sd, NULL, read_map, &c, 4, 1) == 0) { + sim_do_commandf (sd, "memory region 0,0x%x", OR1K_DEFAULT_MEM_SIZE); + } + + /* check for/establish the 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; + } + + /* make sure delay slot mode is consistent with the loaded binary */ + if ((or1k_cpucfgr & SPR_FIELD_MASK_SYS_CPUCFGR_ND) && + (STATE_ARCHITECTURE (sd)->mach != bfd_mach_or1knd)) { + sim_io_eprintf (sd, "WARNING: CPUCFGR ND flag set, but loading non-or1knd binary\n"); + } else if (!(or1k_cpucfgr & SPR_FIELD_MASK_SYS_CPUCFGR_ND) && + (STATE_ARCHITECTURE (sd)->mach != bfd_mach_or1k)) { + sim_io_eprintf (sd, "WARNING: CPUCFGR ND flag not set, but loading non-or1k binary\n"); + } + + /* Open a copy of the cpu descriptor table. */ + { + CGEN_CPU_DESC cd = or1k_cgen_cpu_open_1 (STATE_ARCHITECTURE (sd)->printable_name, + CGEN_ENDIAN_BIG); + for (i = 0; i < MAX_NR_PROCESSORS; ++i) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + CPU_CPU_DESC (cpu) = cd; + CPU_DISASSEMBLER (cpu) = sim_cgen_disassemble_insn; + } + or1k_cgen_init_dis (cd); + } + + /* Initialize various cgen things not done by common framework. + Must be done after or1k_cgen_cpu_open. */ + cgen_init (sd); + + for (c = 0; c < MAX_NR_PROCESSORS; ++c) + { + SIM_CPU *cpu = STATE_CPU (sd, i); + /* Only needed for profiling, but the structure member is small. */ + memset (CPU_OR1K_MISC_PROFILE (cpu), 0, + sizeof (* CPU_OR1K_MISC_PROFILE (cpu))); + +#ifdef WANT_CPU_OR1K32BF + or1k32bf_h_spr_set_raw(cpu, SPR_ADDR(SYS,VR), or1k_vr); + or1k32bf_h_spr_set_raw(cpu, SPR_ADDR(SYS,UPR), or1k_upr); + or1k32bf_h_spr_set_raw(cpu, SPR_ADDR(SYS,CPUCFGR), or1k_cpucfgr); + + or1k32bf_cpu_init (sd, cpu); +#endif + } + + /* Store in a global so things like sparc32_dump_regs can be invoked + from the gdb command line. */ + current_state = sd; + + return sd; +} + + +SIM_RC +sim_create_inferior (sd, abfd, argv, envp) + SIM_DESC sd; + struct bfd *abfd; + char * const *argv; + char * const *envp; +{ + SIM_CPU *current_cpu = STATE_CPU (sd, 0); + SIM_ADDR addr; + + if (abfd != NULL) + addr = bfd_get_start_address (abfd); + else + addr = 0; + sim_pc_set (current_cpu, addr); + + return SIM_RC_OK; +} diff --git a/sim/or1k/sim-main.h b/sim/or1k/sim-main.h new file mode 100644 index 0000000..f0b4e07 --- /dev/null +++ b/sim/or1k/sim-main.h @@ -0,0 +1,78 @@ +#ifndef SIM_MAIN_H +#define SIM_MAIN_H + +#define WITH_SCACHE_PBB 1 + +#include "ansidecl.h" +#include "or1k-desc.h" +#include "sim-basics.h" +#include "cgen-types.h" +#include "arch.h" +typedef IAI sim_cia; +#define CIA_GET(cpu) CPU_PC_GET (cpu) +#define CIA_SET(cpu,val) CPU_PC_SET ((cpu),(val)) +#include "sim-base.h" + +typedef struct _sim_cpu SIM_CPU; +#include "or1k-opc.h" +#include "cgen-sim.h" +#include "or1k-sim.h" +#include "cpuall.h" +#include "or1k.h" + +#ifdef OR1K_LINUX +#define OR1K_DEFAULT_MEM_SIZE 0x2000000 /* 32M */ +#else +#define OR1K_DEFAULT_MEM_SIZE 0x800000 /* 8M */ +#endif + +/* The _sim_cpu struct. */ +struct _sim_cpu { + /* sim/common cpu base. */ + sim_cpu_base base; + + /* Static parts of cgen. */ + CGEN_CPU cgen_cpu; + + OR1K_MISC_PROFILE or1k_misc_profile; +#define CPU_OR1K_MISC_PROFILE(cpu) (& (cpu)->or1k_misc_profile) + + /* CPU specific parts go here. + Note that in files that don't need to access these pieces WANT_CPU_FOO + won't be defined and thus these parts won't appear. This is ok in the + sense that things work. It is a source of bugs though. + One has to of course be careful to not take the size of this + struct and no structure members accessed in non-cpu specific files can + go after here. Oh for a better language. */ + UWI spr[NUM_SPR]; + + /* next instruction will be in delay slot */ + BI next_delay_slot; + /* currently in delay slot */ + BI delay_slot; + +#ifdef WANT_CPU_OR1K32BF + OR1K32BF_CPU_DATA cpu_data; +#endif +#ifdef WANT_CPU_OR1K64BF + OR1K64BF_CPU_DATA cpu_data; +#endif + +}; + +/* The sim_state struct. */ + +struct sim_state { + sim_cpu *cpu[MAX_NR_PROCESSORS]; +#if (WITH_SMP) +#define STATE_CPU(sd, n) ((sd)->cpu[n]) +#else +#define STATE_CPU(sd, n) ((sd)->cpu[0]) +#endif + + CGEN_STATE cgen_state; + + sim_state_base base; +}; + +#endif diff --git a/sim/or1k/traps-linux.c b/sim/or1k/traps-linux.c new file mode 100644 index 0000000..784992a --- /dev/null +++ b/sim/or1k/traps-linux.c @@ -0,0 +1,32 @@ +#include "sim-main.h" + +SEM_PC +sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) +{ + /* TODO */ + abort(); +} + +void or1k32bf_exception (sim_cpu *current_cpu, USI pc, USI exnum) +{ + /* TODO */ + abort(); +} + +void or1k32bf_rfe (sim_cpu *current_cpu) +{ + /* TODO */ + abort(); +} + +USI or1k32bf_mfspr (sim_cpu *current_cpu, USI addr) +{ + /* TODO */ + abort(); +} + +void or1k32bf_mtspr (sim_cpu *current_cpu, USI addr, USI val) +{ + /* TODO */ + abort(); +} diff --git a/sim/or1k/traps.c b/sim/or1k/traps.c new file mode 100644 index 0000000..815b02d --- /dev/null +++ b/sim/or1k/traps.c @@ -0,0 +1,181 @@ +#ifndef WANT_OR1K64 +#define WANT_CPU or1k32bf +#define WANT_CPU_OR1K32BF +#else +#define WANT_CPU or1k64bf +#define WANT_CPU_OR1K64BF +#endif + +#include "sim-main.h" +#include "cgen-ops.h" + +SEM_PC +sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc) +{ + SET_H_SYS_EEAR0(cia); + +#ifdef WANT_CPU_OR1K32BF + or1k32bf_exception (current_cpu, cia, EXCEPT_ILLEGAL); +#endif + + return vpc; +} + +void or1k32bf_exception (sim_cpu *current_cpu, USI pc, USI exnum) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + if (exnum == EXCEPT_TRAP) { + /* Trap, used for breakpoints, sends control back to gdb breakpoint handling */ + sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGTRAP); + } else { + + /* Calculate the exception program counter */ + switch (exnum) { + case EXCEPT_RESET: + break; + + case EXCEPT_SYSCALL: + SET_H_SYS_EPCR0 (pc + 4 - (current_cpu->delay_slot ? 4 : 0)); + break; + + case EXCEPT_BUSERR: + case EXCEPT_ALIGN: + case EXCEPT_ILLEGAL: + SET_H_SYS_EPCR0 (pc - (current_cpu->delay_slot ? 4 : 0)); + break; + + default: + sim_io_error (sd, "unexpected exception 0x%x raised at PC 0x%08x", exnum, pc); + break; + } + + /* Store the curent SR into ESR0 */ + SET_H_SYS_ESR0 (GET_H_SYS_SR ()); + + /* Indicate in SR if the failed instruction is in delay slot or not */ + SET_H_SYS_SR_DSX (current_cpu->delay_slot); + + current_cpu->next_delay_slot = 0; + + /* jump program counter into handler */ + IADDR handler_pc = (GET_H_SYS_SR_EPH() ? 0xf0000000 : 0x00000000) + (exnum << 8); + + sim_engine_restart (sd, current_cpu, NULL, handler_pc); + } +} + +void or1k32bf_rfe (sim_cpu *current_cpu) +{ + SET_H_SYS_SR (GET_H_SYS_ESR0 ()); + SET_H_SYS_SR_FO (1); + + current_cpu->next_delay_slot = 0; + + sim_engine_restart (CPU_STATE (current_cpu), + current_cpu, + NULL, + GET_H_SYS_EPCR0 ()); +} + +USI or1k32bf_mfspr (sim_cpu *current_cpu, USI addr) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + if (!GET_H_SYS_SR_SM () && !GET_H_SYS_SR_SUMRA ()) { + sim_io_eprintf(sd, "WARNING: l.mfspr in user mode (SR 0x%x)\n", GET_H_SYS_SR()); + return 0; + } + + if (addr >= NUM_SPR) + goto bad_address; + + SI val = GET_H_SPR(addr); + + switch (addr) { + + case SPR_ADDR(SYS,VR): + case SPR_ADDR(SYS,UPR): + case SPR_ADDR(SYS,CPUCFGR): + case SPR_ADDR(SYS,SR): + case SPR_ADDR(SYS,PPC): + case SPR_ADDR(SYS,FPCSR): + case SPR_ADDR(SYS,EPCR0): + case SPR_ADDR(MAC,MACLO): + case SPR_ADDR(MAC,MACHI): + break; + + default: + if (addr < SPR_ADDR(SYS,GPR0) || addr > SPR_ADDR(SYS,GPR511)) { + goto bad_address; + } + break; + + } + + return val; + + bad_address: + sim_io_eprintf (sd, "WARNING: l.mfspr with invalid SPR address 0x%x\n", addr); + return 0; + +} + +void or1k32bf_mtspr (sim_cpu *current_cpu, USI addr, USI val) +{ + SIM_DESC sd = CPU_STATE(current_cpu); + + if (!GET_H_SYS_SR_SM () && !GET_H_SYS_SR_SUMRA ()) { + sim_io_eprintf(sd, "WARNING: l.mtspr with address 0x%x in user mode (SR 0x%x)\n", addr, GET_H_SYS_SR()); + return; + } + + if (addr >= NUM_SPR) + goto bad_address; + + switch (addr) { + + case SPR_ADDR(SYS,FPCSR): + case SPR_ADDR(SYS,EPCR0): + case SPR_ADDR(SYS,ESR0): + case SPR_ADDR(MAC,MACHI): + case SPR_ADDR(MAC,MACLO): + SET_H_SPR(addr, val); + break; + + case SPR_ADDR(SYS,SR): + SET_H_SPR(addr, val); + SET_H_SYS_SR_FO(1); + break; + + case SPR_ADDR(SYS,NPC): + current_cpu->next_delay_slot = 0; + + sim_engine_restart (CPU_STATE (current_cpu), + current_cpu, + NULL, + val); + break; + + case SPR_ADDR(TICK,TTMR): + /* allow some registers to be silently cleared */ + if (val != 0) + sim_io_eprintf (sd, "WARNING: l.mtspr to SPR address 0x%x with invalid value 0x%x\n", addr, val); + break; + + default: + if (addr >= SPR_ADDR(SYS,GPR0) && addr <= SPR_ADDR(SYS,GPR511)) { + SET_H_SPR(addr, val); + } else { + goto bad_address; + } + break; + + } + + return; + + bad_address: + sim_io_eprintf (sd, "WARNING: l.mtspr with invalid SPR address 0x%x\n", addr); + +}