xref: /netbsd-src/external/gpl3/gdb/dist/sim/m32r/mloop.in (revision 05fa08567a80471fd0eb3843a238392874f2577c)
1# Simulator main loop for m32r. -*- C -*-
2#
3# Copyright (C) 1996-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 *
49extract16 (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
54  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
55  if (! fast_p)
56    {
57      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
58      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
59      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
60    }
61  return id;
62}
63
64static INLINE const IDESC *
65extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
66	   ARGBUF *abuf, int fast_p)
67{
68  const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf);
69
70  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
71  if (! fast_p)
72    {
73      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
74      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
75      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
76    }
77  return id;
78}
79
80static INLINE SEM_PC
81execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
82{
83  SEM_PC vpc;
84
85  if (fast_p)
86    {
87#if ! WITH_SEM_SWITCH_FAST
88#if WITH_SCACHE
89      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
90#else
91      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf);
92#endif
93#else
94      abort ();
95#endif /* WITH_SEM_SWITCH_FAST */
96    }
97  else
98    {
99#if ! WITH_SEM_SWITCH_FULL
100      ARGBUF *abuf = &sc->argbuf;
101      const IDESC *idesc = abuf->idesc;
102      const CGEN_INSN *idata = idesc->idata;
103#if WITH_SCACHE_PBB
104      int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL);
105#else
106      int virtual_p = 0;
107#endif
108
109      if (! virtual_p)
110	{
111	  /* FIXME: call x-before */
112	  if (ARGBUF_PROFILE_P (abuf))
113	    PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num);
114	  /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}.  */
115	  if (PROFILE_MODEL_P (current_cpu)
116	      && ARGBUF_PROFILE_P (abuf))
117	    @cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
118	  CGEN_TRACE_INSN_INIT (current_cpu, abuf, 1);
119	  CGEN_TRACE_INSN (current_cpu, idata,
120		      (const struct argbuf *) abuf, abuf->addr);
121	}
122#if WITH_SCACHE
123      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
124#else
125      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf);
126#endif
127      if (! virtual_p)
128	{
129	  /* FIXME: call x-after */
130	  if (PROFILE_MODEL_P (current_cpu)
131	      && ARGBUF_PROFILE_P (abuf))
132	    {
133	      int cycles;
134
135	      cycles = (*idesc->timing->model_fn) (current_cpu, sc);
136	      @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
137	    }
138	  CGEN_TRACE_INSN_FINI (current_cpu, abuf, 1);
139	}
140#else
141      abort ();
142#endif /* WITH_SEM_SWITCH_FULL */
143    }
144
145  return vpc;
146}
147
148EOF
149
150;;
151
152xinit)
153
154# Nothing needed.
155
156;;
157
158xextract-simple | xextract-scache)
159
160cat <<EOF
161#line $LINENO "$0"
162{
163  if ((pc & 3) != 0)
164    {
165      /* This only occurs when single stepping.
166	 The test is unnecessary otherwise, but the cost is teensy,
167	 compared with decoding/extraction.  */
168      UHI insn = GETIMEMUHI (current_cpu, pc);
169      extract16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P);
170    }
171  else
172    {
173      USI insn = GETIMEMUSI (current_cpu, pc);
174      if ((SI) insn < 0)
175	{
176	  extract32 (current_cpu, pc, insn, sc, FAST_P);
177	}
178      else
179	{
180	  extract16 (current_cpu, pc, insn >> 16, sc, FAST_P);
181	  extract16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST_P);
182	  /* The m32r doesn't support parallel execution.  */
183	  if ((insn & 0x8000) != 0
184	      && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
185	    sim_engine_illegal_insn (current_cpu, pc);
186	}
187    }
188}
189EOF
190
191;;
192
193xextract-pbb)
194
195# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
196# Outputs: sc, pc
197# sc must be left pointing past the last created entry.
198# pc must be left pointing past the last created entry.
199# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
200# to record the vpc of the cti insn.
201# SET_INSN_COUNT(n) must be called to record number of real insns.
202
203cat <<EOF
204#line $LINENO "$0"
205{
206  const IDESC *idesc;
207  int icount = 0;
208
209  if ((pc & 3) != 0)
210    {
211      /* This only occurs when single stepping.
212	 The test is unnecessary otherwise, but the cost is teensy,
213	 compared with decoding/extraction.  */
214      UHI insn = GETIMEMUHI (current_cpu, pc);
215      idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
216      ++sc;
217      --max_insns;
218      ++icount;
219      pc += 2;
220      if (IDESC_CTI_P (idesc))
221	{
222	  SET_CTI_VPC (sc - 1);
223	  goto Finish;
224	}
225    }
226
227  while (max_insns > 0)
228    {
229      USI insn = GETIMEMUSI (current_cpu, pc);
230      if ((SI) insn < 0)
231	{
232	  idesc = extract32 (current_cpu, pc, insn, &sc->argbuf, FAST_P);
233	  ++sc;
234	  --max_insns;
235	  ++icount;
236	  pc += 4;
237	  if (IDESC_CTI_P (idesc))
238	    {
239	      SET_CTI_VPC (sc - 1);
240	      break;
241	    }
242	}
243      else
244	{
245	  idesc = extract16 (current_cpu, pc, insn >> 16, &sc->argbuf, FAST_P);
246	  ++sc;
247	  --max_insns;
248	  ++icount;
249	  pc += 2;
250	  if (IDESC_CTI_P (idesc))
251	    {
252	      SET_CTI_VPC (sc - 1);
253	      break;
254	    }
255	  /* The m32r doesn't support parallel execution.  */
256	  if ((insn & 0x8000) != 0)
257	    {
258	      /* ??? Defer signalling to execution.  */
259	      if ((insn & 0x7fff) != 0x7000) /* parallel nops are ok */
260		sim_engine_invalid_insn (current_cpu, pc - 2, 0);
261	      /* There's no point in processing parallel nops in fast mode.
262		 We might as well do this test since we've already tested
263		 that we have a parallel nop.  */
264	      if (0 && FAST_P)
265		{
266		  pc += 2;
267		  continue;
268		}
269	    }
270	  else
271	    {
272	      /* Non-parallel case.
273		 While we're guaranteed that there's room to extract the
274		 insn, when single stepping we can't; the pbb must stop
275		 after the first insn.  */
276	      if (max_insns == 0)
277		break;
278	    }
279	  /* We're guaranteed that we can always process 16 bit insns in
280	     pairs.  */
281	  idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
282	  ++sc;
283	  --max_insns;
284	  ++icount;
285	  pc += 2;
286	  if (IDESC_CTI_P (idesc))
287	    {
288	      SET_CTI_VPC (sc - 1);
289	      break;
290	    }
291	}
292    }
293
294 Finish:
295  SET_INSN_COUNT (icount);
296}
297EOF
298
299;;
300
301xfull-exec-* | xfast-exec-*)
302
303# Inputs: current_cpu, vpc, FAST_P
304# Outputs: vpc
305# vpc is the virtual program counter.
306
307cat <<EOF
308#line $LINENO "$0"
309#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
310#define DEFINE_SWITCH
311#include "sem-switch.c"
312#else
313  vpc = execute (current_cpu, vpc, FAST_P);
314#endif
315EOF
316
317;;
318
319*)
320  echo "Invalid argument to mainloop.in: $1" >&2
321  exit 1
322  ;;
323
324esac
325