xref: /netbsd-src/external/gpl3/gdb/dist/sim/or1k/mloop.in (revision 1f4e7eb9e5e045e008f1894823a8e4e6c9f46890)
1# Simulator main loop for or1k. -*- C -*-
2#
3# Copyright (C) 2017-2024 Free Software Foundation, Inc.
4#
5# This file is part of the GNU Simulators.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20# Syntax:
21# /bin/sh mainloop.in command
22#
23# Command is one of:
24#
25# init
26# support
27# extract-{simple,scache,pbb}
28# {full,fast}-exec-{simple,scache,pbb}
29#
30# A target need only provide a "full" version of one of simple,scache,pbb.
31# If the target wants it can also provide a fast version of same, or if
32# the slow (full featured) version is `simple', then the fast version can be
33# one of scache/pbb.
34# A target can't provide more than this.
35# However for illustration's sake this file provides examples of all.
36
37# ??? After a few more ports are done, revisit.
38# Will eventually need to machine generate a lot of this.
39
40case "x$1" in
41
42xsupport)
43
44cat <<EOF
45#line $LINENO "$0"
46#include <stdlib.h>
47
48static INLINE const IDESC *
49extract (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
50         ARGBUF *abuf, int fast_p)
51{
52  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
53  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
54  if (!fast_p)
55    {
56      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
57      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
58      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
59    }
60  return id;
61}
62
63static INLINE SEM_PC
64execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
65{
66  SEM_PC vpc = sc;
67
68  @cpu@_insn_before (current_cpu, vpc, sc->argbuf.idesc);
69
70  if (fast_p)
71    {
72#if ! WITH_SEM_SWITCH_FAST
73#if WITH_SCACHE
74      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
75#else
76      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf);
77#endif
78#else
79      abort ();
80#endif /* WITH_SEM_SWITCH_FAST */
81    }
82  else
83    {
84#if ! WITH_SEM_SWITCH_FULL
85      ARGBUF *abuf = &sc->argbuf;
86      const IDESC *idesc = abuf->idesc;
87      const CGEN_INSN *idata = idesc->idata;
88#if WITH_SCACHE_PBB
89      int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL);
90#else
91      int virtual_p = 0;
92#endif
93
94      if (! virtual_p)
95        {
96          /* FIXME: call x-before */
97          if (ARGBUF_PROFILE_P (abuf))
98            PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num);
99          /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}.  */
100          if (PROFILE_MODEL_P (current_cpu)
101              && ARGBUF_PROFILE_P (abuf))
102            @cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
103          CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1);
104          CGEN_TRACE_INSN (current_cpu, idata,
105                      (const struct argbuf *) abuf, abuf->addr);
106        }
107#if WITH_SCACHE
108      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
109#else
110      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf);
111#endif
112      if (! virtual_p)
113        {
114          /* FIXME: call x-after */
115          if (PROFILE_MODEL_P (current_cpu)
116              && ARGBUF_PROFILE_P (abuf))
117            {
118              int cycles;
119
120              cycles = (*idesc->timing->model_fn) (current_cpu, sc);
121              @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
122            }
123          CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1);
124        }
125#else
126      abort ();
127#endif /* WITH_SEM_SWITCH_FULL */
128    }
129
130  @cpu@_insn_after (current_cpu, vpc, sc->argbuf.idesc);
131
132  return vpc;
133}
134
135EOF
136
137;;
138
139xinit)
140
141# Nothing needed.
142
143;;
144
145xextract-simple | xextract-scache)
146
147cat <<EOF
148#line $LINENO "$0"
149{
150  USI insn = GETIMEMUSI (current_cpu, pc);
151  extract (current_cpu, pc, insn, sc, FAST_P);
152  SEM_SKIP_COMPILE (current_cpu, sc, 1);
153}
154EOF
155
156;;
157
158xextract-pbb)
159
160# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
161# Outputs: sc, pc
162# sc must be left pointing past the last created entry.
163# pc must be left pointing past the last created entry.
164# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
165# to record the vpc of the cti insn.
166# SET_INSN_COUNT(n) must be called to record number of real insns.
167
168cat <<EOF
169#line $LINENO "$0"
170{
171  const IDESC *idesc;
172  int icount = 0;
173
174  while (max_insns > 0) {
175
176    USI insn = GETIMEMUSI (current_cpu, pc);
177
178    idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P);
179
180    SEM_SKIP_COMPILE (current_cpu, sc, 1);
181
182    ++sc;
183    --max_insns;
184    ++icount;
185    pc += 4;
186
187    if (CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_FORCED_CTI))
188      {
189
190        SET_CTI_VPC (sc - 1);
191
192        break;
193
194      }
195    else if (CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI))
196      {
197
198        /* handle delay slot */
199        SET_CTI_VPC (sc - 1);
200
201        insn = GETIMEMUSI (current_cpu, pc);
202
203        idesc = extract (current_cpu, pc, insn, &sc->argbuf, FAST_P);
204
205        ++sc;
206        --max_insns;
207        ++icount;
208        pc += 4;
209
210        break;
211      }
212  }
213
214  SET_INSN_COUNT (icount);
215
216}
217EOF
218
219;;
220
221xfull-exec-* | xfast-exec-*)
222
223# Inputs: current_cpu, vpc, FAST_P
224# Outputs: vpc
225# vpc is the virtual program counter.
226
227cat <<EOF
228#line $LINENO "$0"
229#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
230#define DEFINE_SWITCH
231#ifdef WANT_CPU_OR1K32BF
232#include "sem-switch.c"
233#endif
234#else
235  vpc = execute (current_cpu, vpc, FAST_P);
236#endif
237EOF
238
239;;
240
241*)
242  echo "Invalid argument to mainloop.in: $1" >&2
243  exit 1
244  ;;
245
246esac
247