1 # Simulator main loop for m32r2. -*- C -*-
3 # Copyright 1996-2024 Free Software Foundation, Inc.
5 # This file is part of GDB, the GNU debugger.
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/>.
21 # /bin/sh mainloop.in command
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
34 # A target can't provide more than this.
36 # ??? After a few more ports are done, revisit.
37 # Will eventually need to machine generate a lot of this.
46 /* Emit insns to write back the results of insns executed in parallel.
47 SC points to a sufficient number of scache entries for the writeback
49 SC1/ID1 is the first insn (left slot, lower address).
50 SC2/ID2 is the second insn (right slot, higher address). */
53 emit_par_finish (SIM_CPU *current_cpu, PCADDR pc, SCACHE *sc,
54 SCACHE *sc1, const IDESC *id1, SCACHE *sc2, const IDESC *id2)
60 abuf->fields.write.abuf = &sc1->argbuf;
61 @cpu@_fill_argbuf (current_cpu, abuf, id1, pc, 0);
62 /* no need to set trace_p,profile_p */
63 #if 0 /* not currently needed for id2 since results written directly */
66 abuf->fields.write.abuf = &sc2->argbuf;
67 @cpu@_fill_argbuf (current_cpu, abuf, id2, pc + 2, 0);
68 /* no need to set trace_p,profile_p */
72 static INLINE const IDESC *
73 emit_16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
74 SCACHE *sc, int fast_p, int parallel_p)
76 ARGBUF *abuf = &sc->argbuf;
77 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
81 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
85 static INLINE const IDESC *
86 emit_full16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
87 int trace_p, int profile_p)
91 @cpu@_emit_before (current_cpu, sc, pc, 1);
92 id = emit_16 (current_cpu, pc, insn, sc + 1, 0, 0);
93 @cpu@_emit_after (current_cpu, sc + 2, pc);
94 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
98 static INLINE const IDESC *
99 emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
100 SCACHE *sc, int fast_p)
102 const IDESC *id,*id2;
104 /* Emit both insns, then emit a finisher-upper.
105 We speed things up by handling the second insn serially
106 [not parallelly]. Then the writeback only has to deal
107 with the first insn. */
108 /* ??? Revisit to handle exceptions right. */
110 /* FIXME: No need to handle this parallely if second is nop. */
111 id = emit_16 (current_cpu, pc, insn >> 16, sc, fast_p, 1);
113 /* Note that this can never be a cti. No cti's go in the S pipeline. */
114 id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, fast_p, 0);
116 /* Set sc/snc insns notion of where to skip to. */
117 if (IDESC_SKIP_P (id))
118 SEM_SKIP_COMPILE (current_cpu, sc, 1);
120 /* Emit code to finish executing the semantics
121 (write back the results). */
122 emit_par_finish (current_cpu, pc, sc + 2, sc, id, sc + 1, id2);
127 static INLINE const IDESC *
128 emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
129 SCACHE *sc, int trace_p, int profile_p)
131 const IDESC *id,*id2;
133 /* Emit both insns, then emit a finisher-upper.
134 We speed things up by handling the second insn serially
135 [not parallelly]. Then the writeback only has to deal
136 with the first insn. */
137 /* ??? Revisit to handle exceptions right. */
139 @cpu@_emit_before (current_cpu, sc, pc, 1);
141 /* FIXME: No need to handle this parallelly if second is nop. */
142 id = emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 1);
143 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
145 @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
147 /* Note that this can never be a cti. No cti's go in the S pipeline. */
148 id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 3, 0, 0);
149 @cpu@_fill_argbuf_tp (current_cpu, &sc[3].argbuf, trace_p, profile_p);
151 /* Set sc/snc insns notion of where to skip to. */
152 if (IDESC_SKIP_P (id))
153 SEM_SKIP_COMPILE (current_cpu, sc, 4);
155 /* Emit code to finish executing the semantics
156 (write back the results). */
157 emit_par_finish (current_cpu, pc, sc + 4, sc + 1, id, sc + 3, id2);
159 @cpu@_emit_after (current_cpu, sc + 5, pc);
164 static INLINE const IDESC *
165 emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
166 SCACHE *sc, int fast_p)
168 ARGBUF *abuf = &sc->argbuf;
169 const IDESC *id = @cpu@_decode (current_cpu, pc,
170 (USI) insn >> 16, insn, abuf);
172 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
176 static INLINE const IDESC *
177 emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
178 int trace_p, int profile_p)
182 @cpu@_emit_before (current_cpu, sc, pc, 1);
183 id = emit_32 (current_cpu, pc, insn, sc + 1, 0);
184 @cpu@_emit_after (current_cpu, sc + 2, pc);
185 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
201 # Inputs: current_cpu, pc, sc, max_insns, FAST_P
203 # sc must be left pointing past the last created entry.
204 # pc must be left pointing past the last created entry.
205 # If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
206 # to record the vpc of the cti insn.
207 # SET_INSN_COUNT(n) must be called to record number of real insns.
217 /* This occurs when single stepping and when compiling the not-taken
218 part of conditional branches. */
219 UHI insn = GETIMEMUHI (current_cpu, pc);
220 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
221 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
222 SCACHE *cti_sc; /* ??? tmp hack */
224 /* A parallel insn isn't allowed here, but we don't mind nops.
225 ??? We need to wait until the insn is executed before signalling
226 the error, for situations where such signalling is wanted. */
228 if ((insn & 0x8000) != 0
229 && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
230 sim_engine_invalid_insn (current_cpu, pc, 0);
233 /* Only emit before/after handlers if necessary. */
234 if (FAST_P || (! trace_p && ! profile_p))
236 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
243 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
251 if (IDESC_CTI_P (idesc))
253 SET_CTI_VPC (cti_sc);
258 /* There are two copies of the compiler: full(!fast) and fast.
259 The "full" case emits before/after handlers for each insn.
260 Having two copies of this code is a tradeoff, having one copy
261 seemed a bit more difficult to read (due to constantly testing
262 FAST_P). ??? On the other hand, with address ranges we'll want to
263 omit before/after handlers for unwanted insns. Having separate loops
264 for FAST/!FAST avoids constantly doing the test in the loop, but
265 typically FAST_P is a constant and such tests will get optimized out. */
269 while (max_insns > 0)
271 USI insn = GETIMEMUSI (current_cpu, pc);
275 idesc = emit_32 (current_cpu, pc, insn, sc, 1);
280 if (IDESC_CTI_P (idesc))
282 SET_CTI_VPC (sc - 1);
288 if ((insn & 0x8000) != 0) /* parallel? */
292 if (((insn >> 16) & 0xfff0) == 0x10f0)
294 /* FIXME: No need to handle this sequentially if system
295 calls will be able to execute after second insn in
296 parallel. ( trap #num || insn ) */
298 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
301 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
306 /* Yep. Here's the "interesting" [sic] part. */
307 idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
311 max_insns -= up_count;
314 if (IDESC_CTI_P (idesc))
316 SET_CTI_VPC (sc - up_count);
320 else /* 2 serial 16 bit insns */
322 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
327 if (IDESC_CTI_P (idesc))
329 SET_CTI_VPC (sc - 1);
332 /* While we're guaranteed that there's room to extract the
333 insn, when single stepping we can't; the pbb must stop
334 after the first insn. */
337 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
342 if (IDESC_CTI_P (idesc))
344 SET_CTI_VPC (sc - 1);
353 while (max_insns > 0)
355 USI insn = GETIMEMUSI (current_cpu, pc);
356 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
357 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
358 SCACHE *cti_sc; /* ??? tmp hack */
362 Only emit before/after handlers if necessary. */
363 if (trace_p || profile_p)
365 idesc = emit_full32 (current_cpu, pc, insn, sc,
373 idesc = emit_32 (current_cpu, pc, insn, sc, 0);
380 if (IDESC_CTI_P (idesc))
382 SET_CTI_VPC (cti_sc);
388 if ((insn & 0x8000) != 0) /* parallel? */
390 /* Yep. Here's the "interesting" [sic] part.
391 Only emit before/after handlers if necessary. */
392 if (trace_p || profile_p)
394 if (((insn >> 16) & 0xfff0) == 0x10f0)
396 /* FIXME: No need to handle this sequentially if
397 system calls will be able to execute after second
398 insn in parallel. ( trap #num || insn ) */
400 idesc = emit_full16 (current_cpu, pc + 2,
401 insn & 0x7fff, sc, 0, 0);
403 emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
408 idesc = emit_full_parallel (current_cpu, pc, insn,
409 sc, trace_p, profile_p);
419 if (((insn >> 16) & 0xfff0) == 0x10f0)
421 /* FIXME: No need to handle this sequentially if
422 system calls will be able to execute after second
423 insn in parallel. ( trap #num || insn ) */
425 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
428 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
433 idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
438 max_insns -= up_count;
442 if (IDESC_CTI_P (idesc))
444 SET_CTI_VPC (cti_sc);
448 else /* 2 serial 16 bit insns */
450 /* Only emit before/after handlers if necessary. */
451 if (trace_p || profile_p)
453 idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
461 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
468 if (IDESC_CTI_P (idesc))
470 SET_CTI_VPC (cti_sc);
473 /* While we're guaranteed that there's room to extract the
474 insn, when single stepping we can't; the pbb must stop
475 after the first insn. */
478 /* Use the same trace/profile address for the 2nd insn.
479 Saves us having to compute it and they come in pairs
480 anyway (e.g. can never branch to the 2nd insn). */
481 if (trace_p || profile_p)
483 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
491 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
498 if (IDESC_CTI_P (idesc))
500 SET_CTI_VPC (cti_sc);
509 SET_INSN_COUNT (icount);
517 # Inputs: current_cpu, vpc, FAST_P
519 # vpc is the virtual program counter.
523 #define DEFINE_SWITCH
524 #include "sem2-switch.c"
530 echo "Invalid argument to mainloop.in: $1" >&2