Automatic date update in version.in
[binutils-gdb.git] / sim / m32r / mloop.in
blob01fa09531403457873e49f4df84593c6bbbad537
1 # Simulator main loop for m32r. -*- C -*-
3 # Copyright (C) 1996-2024 Free Software Foundation, Inc.
5 # This file is part of the GNU Simulators.
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.
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.
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/>.
20 # Syntax:
21 # /bin/sh mainloop.in command
23 # Command is one of:
25 # init
26 # support
27 # extract-{simple,scache,pbb}
28 # {full,fast}-exec-{simple,scache,pbb}
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.
37 # ??? After a few more ports are done, revisit.
38 # Will eventually need to machine generate a lot of this.
40 case "x$1" in
42 xsupport)
44 cat <<EOF
45 #line $LINENO "$0"
46 #include <stdlib.h>
48 static INLINE const IDESC *
49 extract16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
50            ARGBUF *abuf, int fast_p)
52   const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
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;
64 static INLINE const IDESC *
65 extract32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
66            ARGBUF *abuf, int fast_p)
68   const IDESC *id = @cpu@_decode (current_cpu, pc, (USI) insn >> 16, insn, abuf);
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;
80 static INLINE SEM_PC
81 execute (SIM_CPU *current_cpu, SCACHE *sc, int fast_p)
83   SEM_PC vpc;
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
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;
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     }
145   return vpc;
152 xinit)
154 # Nothing needed.
158 xextract-simple | xextract-scache)
160 cat <<EOF
161 #line $LINENO "$0"
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     }
193 xextract-pbb)
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.
203 cat <<EOF
204 #line $LINENO "$0"
206   const IDESC *idesc;
207   int icount = 0;
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     }
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     }
294  Finish:
295   SET_INSN_COUNT (icount);
301 xfull-exec-* | xfast-exec-*)
303 # Inputs: current_cpu, vpc, FAST_P
304 # Outputs: vpc
305 # vpc is the virtual program counter.
307 cat <<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
320   echo "Invalid argument to mainloop.in: $1" >&2
321   exit 1
322   ;;
324 esac