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