1# Simulator main loop for m32r. -*- C -*-
2# Copyright (C) 1996, 1997, 1998, 2007 Free Software Foundation, Inc.
3#
4# This file is part of the GNU Simulators.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19# Syntax:
20# /bin/sh mainloop.in command
21#
22# Command is one of:
23#
24# init
25# support
26# extract-{simple,scache,pbb}
27# {full,fast}-exec-{simple,scache,pbb}
28#
29# A target need only provide a "full" version of one of simple,scache,pbb.
30# If the target wants it can also provide a fast version of same, or if
31# the slow (full featured) version is `simple', then the fast version can be
32# one of scache/pbb.
33# A target can't provide more than this.
34# However for illustration's sake this file provides examples of all.
35
36# ??? After a few more ports are done, revisit.
37# Will eventually need to machine generate a lot of this.
38
39case "x$1" in
40
41xsupport)
42
43cat <<EOF
44
45static INLINE const IDESC *
46extract16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
47	   ARGBUF *abuf, int fast_p)
48{
49  const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
50
51  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
52  if (! fast_p)
53    {
54      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
55      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
56      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
57    }
58  return id;
59}
60
61static INLINE const IDESC *
62extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
63	   ARGBUF *abuf, int fast_p)
64{
65  const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf);
66
67  @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
68  if (! fast_p)
69    {
70      int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
71      int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
72      @cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
73    }
74  return id;
75}
76
77static INLINE SEM_PC
78execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
79{
80  SEM_PC vpc;
81
82  if (fast_p)
83    {
84#if ! WITH_SEM_SWITCH_FAST
85#if WITH_SCACHE
86      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, sc);
87#else
88      vpc = (*sc->argbuf.semantic.sem_fast) (current_cpu, &sc->argbuf);
89#endif
90#else
91      abort ();
92#endif /* WITH_SEM_SWITCH_FAST */
93    }
94  else
95    {
96#if ! WITH_SEM_SWITCH_FULL
97      ARGBUF *abuf = &sc->argbuf;
98      const IDESC *idesc = abuf->idesc;
99      const CGEN_INSN *idata = idesc->idata;
100#if WITH_SCACHE_PBB
101      int virtual_p = CGEN_INSN_ATTR_VALUE (idata, CGEN_INSN_VIRTUAL);
102#else
103      int virtual_p = 0;
104#endif
105
106      if (! virtual_p)
107	{
108	  /* FIXME: call x-before */
109	  if (ARGBUF_PROFILE_P (abuf))
110	    PROFILE_COUNT_INSN (current_cpu, abuf->addr, idesc->num);
111	  /* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}.  */
112	  if (PROFILE_MODEL_P (current_cpu)
113	      && ARGBUF_PROFILE_P (abuf))
114	    @cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
115	  TRACE_INSN_INIT (current_cpu, abuf, 1);
116	  TRACE_INSN (current_cpu, idata,
117		      (const struct argbuf *) abuf, abuf->addr);
118	}
119#if WITH_SCACHE
120      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, sc);
121#else
122      vpc = (*sc->argbuf.semantic.sem_full) (current_cpu, abuf);
123#endif
124      if (! virtual_p)
125	{
126	  /* FIXME: call x-after */
127	  if (PROFILE_MODEL_P (current_cpu)
128	      && ARGBUF_PROFILE_P (abuf))
129	    {
130	      int cycles;
131
132	      cycles = (*idesc->timing->model_fn) (current_cpu, sc);
133	      @cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
134	    }
135	  TRACE_INSN_FINI (current_cpu, abuf, 1);
136	}
137#else
138      abort ();
139#endif /* WITH_SEM_SWITCH_FULL */
140    }
141
142  return vpc;
143}
144
145EOF
146
147;;
148
149xinit)
150
151# Nothing needed.
152
153;;
154
155xextract-simple | xextract-scache)
156
157cat <<EOF
158{
159  if ((pc & 3) != 0)
160    {
161      /* This only occurs when single stepping.
162	 The test is unnecessary otherwise, but the cost is teensy,
163	 compared with decoding/extraction.  */
164      UHI insn = GETIMEMUHI (current_cpu, pc);
165      extract16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P);
166    }
167  else
168    {
169      USI insn = GETIMEMUSI (current_cpu, pc);
170      if ((SI) insn < 0)
171	{
172	  extract32 (current_cpu, pc, insn, sc, FAST_P);
173	}
174      else
175	{
176	  extract16 (current_cpu, pc, insn >> 16, sc, FAST_P);
177	  extract16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, FAST_P);
178	  /* The m32r doesn't support parallel execution.  */
179	  if ((insn & 0x8000) != 0
180	      && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
181	    sim_engine_illegal_insn (current_cpu, pc);
182	}
183    }
184}
185EOF
186
187;;
188
189xextract-pbb)
190
191# Inputs:  current_cpu, pc, sc, max_insns, FAST_P
192# Outputs: sc, pc
193# sc must be left pointing past the last created entry.
194# pc must be left pointing past the last created entry.
195# If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
196# to record the vpc of the cti insn.
197# SET_INSN_COUNT(n) must be called to record number of real insns.
198
199cat <<EOF
200{
201  const IDESC *idesc;
202  int icount = 0;
203
204  if ((pc & 3) != 0)
205    {
206      /* This only occurs when single stepping.
207	 The test is unnecessary otherwise, but the cost is teensy,
208	 compared with decoding/extraction.  */
209      UHI insn = GETIMEMUHI (current_cpu, pc);
210      idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
211      ++sc;
212      --max_insns;
213      ++icount;
214      pc += 2;
215      if (IDESC_CTI_P (idesc))
216	{
217	  SET_CTI_VPC (sc - 1);
218	  goto Finish;
219	}
220    }
221
222  while (max_insns > 0)
223    {
224      USI insn = GETIMEMUSI (current_cpu, pc);
225      if ((SI) insn < 0)
226	{
227	  idesc = extract32 (current_cpu, pc, insn, &sc->argbuf, FAST_P);
228	  ++sc;
229	  --max_insns;
230	  ++icount;
231	  pc += 4;
232	  if (IDESC_CTI_P (idesc))
233	    {
234	      SET_CTI_VPC (sc - 1);
235	      break;
236	    }
237	}
238      else
239	{
240	  idesc = extract16 (current_cpu, pc, insn >> 16, &sc->argbuf, FAST_P);
241	  ++sc;
242	  --max_insns;
243	  ++icount;
244	  pc += 2;
245	  if (IDESC_CTI_P (idesc))
246	    {
247	      SET_CTI_VPC (sc - 1);
248	      break;
249	    }
250	  /* The m32r doesn't support parallel execution.  */
251	  if ((insn & 0x8000) != 0)
252	    {
253	      /* ??? Defer signalling to execution.  */
254	      if ((insn & 0x7fff) != 0x7000) /* parallel nops are ok */
255		sim_engine_invalid_insn (current_cpu, pc - 2, 0);
256	      /* There's no point in processing parallel nops in fast mode.
257		 We might as well do this test since we've already tested
258		 that we have a parallel nop.  */
259	      if (0 && FAST_P)
260		{
261		  pc += 2;
262		  continue;
263		}
264	    }
265	  else
266	    {
267	      /* Non-parallel case.
268		 While we're guaranteed that there's room to extract the
269		 insn, when single stepping we can't; the pbb must stop
270		 after the first insn.  */
271	      if (max_insns == 0)
272		break;
273	    }
274	  /* We're guaranteed that we can always process 16 bit insns in
275	     pairs.  */
276	  idesc = extract16 (current_cpu, pc, insn & 0x7fff, &sc->argbuf, FAST_P);
277	  ++sc;
278	  --max_insns;
279	  ++icount;
280	  pc += 2;
281	  if (IDESC_CTI_P (idesc))
282	    {
283	      SET_CTI_VPC (sc - 1);
284	      break;
285	    }
286	}
287    }
288
289 Finish:
290  SET_INSN_COUNT (icount);
291}
292EOF
293
294;;
295
296xfull-exec-* | xfast-exec-*)
297
298# Inputs: current_cpu, vpc, FAST_P
299# Outputs: vpc
300# vpc is the virtual program counter.
301
302cat <<EOF
303#if (! FAST_P && WITH_SEM_SWITCH_FULL) || (FAST_P && WITH_SEM_SWITCH_FAST)
304#define DEFINE_SWITCH
305#include "sem-switch.c"
306#else
307  vpc = execute (current_cpu, vpc, FAST_P);
308#endif
309EOF
310
311;;
312
313*)
314  echo "Invalid argument to mainloop.in: $1" >&2
315  exit 1
316  ;;
317
318esac
319