📄 genmloop.sh
字号:
# Generate the main loop of the simulator.# Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.# Contributed by Cygnus Support.## 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 2, 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, write to the Free Software Foundation, Inc.,# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.## This file creates two files: eng.hin and mloop.cin.# eng.hin defines a few macros that specify what kind of engine was selected# based on the arguments to this script.# mloop.cin contains the engine.## ??? Rename mloop.c to eng.c?# ??? Rename mainloop.in to engine.in?# ??? Add options to specify output file names?# ??? Rename this file to genengine.sh?## Syntax: genmloop.sh [options]## Options:## -mono | -multi# - specify single cpu or multiple cpus (number specifyable at runtime),# maximum number is a configuration parameter# - -multi wip## -fast: include support for fast execution in addition to full featured mode## Full featured mode is for tracing, profiling, etc. and is always# provided. Fast mode contains no frills, except speed.# 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. It can't provide more than this.# ??? Later add ability to have another set of full/fast semantics# for use in with-devices/with-smp situations (pbb can be inappropriate# here).## -full-switch: same as -fast but for full featured version of -switch# Only needed if -fast present.## -simple: simple execution engine (the default)## This engine fetches and executes one instruction at a time.# Field extraction is done in the semantic routines.## ??? There are two possible flavours of -simple. One that extracts# fields in the semantic routine (which is what is implemented here),# and one that stores the extracted fields in ARGBUF before calling the# semantic routine. The latter is essentially the -scache case with a# cache size of one (and the scache lookup code removed). There are no# current uses of this and it's not clear when doing this would be a win.# More complicated ISA's that want to use -simple may find this a win.# Should this ever be desirable, implement a new engine style here and# call it -extract (or some such). It's believed that the CGEN-generated# code for the -scache case would be usable here, so no new code# generation option would be needed for CGEN.## -scache: use the scache to speed things up (not always a win)## This engine caches the extracted instruction before executing it.# When executing instructions they are first looked up in the scache.## -pbb: same as -scache but extract a (pseudo-) basic block at a time## This engine is basically identical to the scache version except that# extraction is done a pseudo-basic-block at a time and the address of# the scache entry of a branch target is recorded as well.# Additional speedups are then possible by defering Ctrl-C checking# to the end of basic blocks and by threading the insns together.# We call them pseudo-basic-block's instead of just basic-blocks because# they're not necessarily basic-blocks, though normally are.## -parallel-read: support parallel execution with read-before-exec support.# -parallel-write: support parallel execution with write-after-exec support.# -parallel-generic-write: support parallel execution with generic queued# writes.## One of these options is specified in addition to -simple, -scache,# -pbb. Note that while the code can determine if the cpu supports# parallel execution with HAVE_PARALLEL_INSNS [and thus this option is# technically unnecessary], having this option cuts down on the clutter# in the result.## -parallel-only: semantic code only supports parallel version of insn## Semantic code only supports parallel versions of each insn.# Things can be sped up by generating both serial and parallel versions# and is better suited to mixed parallel architectures like the m32r.## -prefix: string to prepend to function names in mloop.c/eng.h.## If no prefix is specified, the cpu type is used.## -switch file: specify file containing semantics implemented as a switch()## -cpu <cpu-family>## Specify the cpu family name.## -infile <input-file>## Specify the mainloop.in input file.## -outfile-suffix <output-file-suffix>## Specify the suffix to append to output files.## Only one of -scache/-pbb may be selected.# -simple is the default.####### TODO# - build mainloop.in from .cpu filetype=mono#scache=#fast=#full_switch=#pbb=parallel=noparallel_only=noswitch=cpu="unknown"infile=""prefix="unknown"outsuffix=""while test $# -gt 0do case $1 in -mono) type=mono ;; -multi) type=multi ;; -no-fast) ;; -fast) fast=yes ;; -full-switch) full_switch=yes ;; -simple) ;; -scache) scache=yes ;; -pbb) pbb=yes ;; -no-parallel) ;; -outfile-suffix) shift ; outsuffix=$1 ;; -parallel-read) parallel=read ;; -parallel-write) parallel=write ;; -parallel-generic-write) parallel=genwrite ;; -parallel-only) parallel_only=yes ;; -prefix) shift ; prefix=$1 ;; -switch) shift ; switch=$1 ;; -cpu) shift ; cpu=$1 ;; -infile) shift ; infile=$1 ;; *) echo "unknown option: $1" >&2 ; exit 1 ;; esac shiftdone# Argument validation.if [ x$scache = xyes -a x$pbb = xyes ] ; then echo "only one of -scache and -pbb may be selected" >&2 exit 1fiif [ "x$cpu" = xunknown ] ; then echo "cpu family not specified" >&2 exit 1fiif [ "x$infile" = x ] ; then echo "mainloop.in not specified" >&2 exit 1fiif [ "x$prefix" = xunknown ] ; then prefix=$cpufilowercase='abcdefghijklmnopqrstuvwxyz'uppercase='ABCDEFGHIJKLMNOPQRSTUVWXYZ'CPU=`echo ${cpu} | tr "${lowercase}" "${uppercase}"`PREFIX=`echo ${prefix} | tr "${lowercase}" "${uppercase}"`##########################################################################rm -f eng${outsuffix}.hinexec 1>eng${outsuffix}.hinecho "/* engine configuration for ${cpu} */"echo ""echo "/* WITH_FAST: non-zero if a fast version of the engine is available"echo " in addition to the full-featured version. */"if [ x$fast = xyes ] ; then echo "#define WITH_FAST 1"else echo "#define WITH_FAST 0"fiecho ""echo "/* WITH_SCACHE_PBB_${PREFIX}: non-zero if the pbb engine was selected. */"if [ x$pbb = xyes ] ; then echo "#define WITH_SCACHE_PBB_${PREFIX} 1"else echo "#define WITH_SCACHE_PBB_${PREFIX} 0"fiecho ""echo "/* HAVE_PARALLEL_INSNS: non-zero if cpu can parallelly execute > 1 insn. */"# blah blah blah, other ways to do this, blah blah blahcase x$parallel inxno) echo "#define HAVE_PARALLEL_INSNS 0" echo "#define WITH_PARALLEL_READ 0" echo "#define WITH_PARALLEL_WRITE 0" echo "#define WITH_PARALLEL_GENWRITE 0" ;;xread) echo "#define HAVE_PARALLEL_INSNS 1" echo "/* Parallel execution is supported by read-before-exec. */" echo "#define WITH_PARALLEL_READ 1" echo "#define WITH_PARALLEL_WRITE 0" echo "#define WITH_PARALLEL_GENWRITE 0" ;;xwrite) echo "#define HAVE_PARALLEL_INSNS 1" echo "/* Parallel execution is supported by write-after-exec. */" echo "#define WITH_PARALLEL_READ 0" echo "#define WITH_PARALLEL_WRITE 1" echo "#define WITH_PARALLEL_GENWRITE 0" ;;xgenwrite) echo "#define HAVE_PARALLEL_INSNS 1" echo "/* Parallel execution is supported by generic write-after-exec. */" echo "#define WITH_PARALLEL_READ 0" echo "#define WITH_PARALLEL_WRITE 0" echo "#define WITH_PARALLEL_GENWRITE 1" ;;esacif [ "x$switch" != x ] ; then echo "" echo "/* WITH_SEM_SWITCH_FULL: non-zero if full-featured engine is" echo " implemented as a switch(). */" if [ x$fast != xyes -o x$full_switch = xyes ] ; then echo "#define WITH_SEM_SWITCH_FULL 1" else echo "#define WITH_SEM_SWITCH_FULL 0" fi echo "" echo "/* WITH_SEM_SWITCH_FAST: non-zero if fast engine is" echo " implemented as a switch(). */" if [ x$fast = xyes ] ; then echo "#define WITH_SEM_SWITCH_FAST 1" else echo "#define WITH_SEM_SWITCH_FAST 0" fifi# Decls of functions we define.echo ""echo "/* Functions defined in the generated mainloop.c file"echo " (which doesn't necessarily have that file name). */"echo ""echo "extern ENGINE_FN ${prefix}_engine_run_full;"echo "extern ENGINE_FN ${prefix}_engine_run_fast;"if [ x$pbb = xyes ] ; then echo "" echo "extern SEM_PC ${prefix}_pbb_begin (SIM_CPU *, int);" echo "extern SEM_PC ${prefix}_pbb_chain (SIM_CPU *, SEM_ARG);" echo "extern SEM_PC ${prefix}_pbb_cti_chain (SIM_CPU *, SEM_ARG, SEM_BRANCH_TYPE, PCADDR);" echo "extern void ${prefix}_pbb_before (SIM_CPU *, SCACHE *);" echo "extern void ${prefix}_pbb_after (SIM_CPU *, SCACHE *);"fi##########################################################################rm -f tmp-mloop-$$.cin mloop${outsuffix}.cinexec 1>tmp-mloop-$$.cin# We use @cpu@ instead of ${cpu} because we still need to run sed to handle# transformation of @cpu@ for mainloop.in, so there's no need to use ${cpu}# here.cat << EOF/* This file is generated by the genmloop script. DO NOT EDIT! *//* Enable switch() support in cgen headers. */#define SEM_IN_SWITCH#define WANT_CPU @cpu@#define WANT_CPU_@CPU@#include "sim-main.h"#include "bfd.h"#include "cgen-mem.h"#include "cgen-ops.h"#include "sim-assert.h"/* Fill in the administrative ARGBUF fields required by all insns, virtual and real. */static INLINE void@prefix@_fill_argbuf (const SIM_CPU *cpu, ARGBUF *abuf, const IDESC *idesc, PCADDR pc, int fast_p){#if WITH_SCACHE SEM_SET_CODE (abuf, idesc, fast_p); ARGBUF_ADDR (abuf) = pc;#endif ARGBUF_IDESC (abuf) = idesc;}/* Fill in tracing/profiling fields of an ARGBUF. */static INLINE void@prefix@_fill_argbuf_tp (const SIM_CPU *cpu, ARGBUF *abuf, int trace_p, int profile_p){ ARGBUF_TRACE_P (abuf) = trace_p; ARGBUF_PROFILE_P (abuf) = profile_p;}#if WITH_SCACHE_PBB/* Emit the "x-before" handler. x-before is emitted before each insn (serial or parallel). This is as opposed to x-after which is only emitted at the end of a group of parallel insns. */static INLINE void@prefix@_emit_before (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc, int first_p){ ARGBUF *abuf = &sc[0].argbuf; const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_BEFORE]; abuf->fields.before.first_p = first_p; @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0); /* no need to set trace_p,profile_p */}/* Emit the "x-after" handler. x-after is emitted after a serial insn or at the end of a group of parallel insns. */static INLINE void@prefix@_emit_after (SIM_CPU *current_cpu, SCACHE *sc, PCADDR pc){ ARGBUF *abuf = &sc[0].argbuf; const IDESC *id = & CPU_IDESC (current_cpu) [@PREFIX@_INSN_X_AFTER]; @prefix@_fill_argbuf (current_cpu, abuf, id, pc, 0); /* no need to set trace_p,profile_p */}#endif /* WITH_SCACHE_PBB */EOF${SHELL} $infile support########################################################################### Simple engine: fetch an instruction, execute the instruction.## Instruction fields are not extracted into ARGBUF, they are extracted in# the semantic routines themselves. However, there is still a need to pass# and return misc. information to the semantic routines so we still use ARGBUF.# [One could certainly implement things differently and remove ARGBUF.# It's not clear this is necessarily always a win.]# ??? The use of the SCACHE struct is for consistency with the with-scache# case though it might be a source of confusion.if [ x$scache != xyes -a x$pbb != xyes ] ; then cat << EOF#define FAST_P 0void@prefix@_engine_run_full (SIM_CPU *current_cpu){#define FAST_P 0 SIM_DESC current_state = CPU_STATE (current_cpu); /* ??? Use of SCACHE is a bit of a hack as we don't actually use the scache. We do however use ARGBUF so for consistency with the other engine flavours the SCACHE type is used. */ SCACHE cache[MAX_LIW_INSNS]; SCACHE *sc = &cache[0];EOFcase x$parallel inxread | xwrite) cat << EOF PAREXEC pbufs[MAX_PARALLEL_INSNS]; PAREXEC *par_exec;EOF ;;esac# Any initialization code before looping starts.# Note that this code may declare some locals.${SHELL} $infile initif [ x$parallel = xread ] ; then cat << EOF#if defined (__GNUC__) { if (! CPU_IDESC_READ_INIT_P (current_cpu)) {/* ??? Later maybe paste read.c in when building mainloop.c. */#define DEFINE_LABELS#include "readx.c" CPU_IDESC_READ_INIT_P (current_cpu) = 1; } }#endifEOFficat << EOF if (! CPU_IDESC_SEM_INIT_P (current_cpu)) {#if WITH_SEM_SWITCH_FULL#if defined (__GNUC__)/* ??? Later maybe paste sem-switch.c in when building mainloop.c. */#define DEFINE_LABELS#include "$switch"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -