]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/m32r/mloop2.in
Update gdb/NEWS after GDB 15 branch creation.
[thirdparty/binutils-gdb.git] / sim / m32r / mloop2.in
CommitLineData
4b09af6f 1# Simulator main loop for m32r2. -*- C -*-
df2a9ff4 2#
1d506c26 3# Copyright 1996-2024 Free Software Foundation, Inc.
4b09af6f
NC
4#
5# This file is part of GDB, the GNU debugger.
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
4744ac1b
JB
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
4b09af6f
NC
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#
4744ac1b
JB
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/>.
4b09af6f
NC
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
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
6003fe16 44#line $LINENO "$0"
4b09af6f
NC
45
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
48 handlers.
49 SC1/ID1 is the first insn (left slot, lower address).
50 SC2/ID2 is the second insn (right slot, higher address). */
51
52static INLINE void
53emit_par_finish (SIM_CPU *current_cpu, PCADDR pc, SCACHE *sc,
54 SCACHE *sc1, const IDESC *id1, SCACHE *sc2, const IDESC *id2)
55{
56 ARGBUF *abuf;
57
58 abuf = &sc->argbuf;
59 id1 = id1->par_idesc;
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 */
64 abuf = &sc[1].argbuf;
65 id2 = id2->par_idesc;
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 */
69#endif
70}
71
72static INLINE const IDESC *
73emit_16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
74 SCACHE *sc, int fast_p, int parallel_p)
75{
76 ARGBUF *abuf = &sc->argbuf;
77 const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
78
79 if (parallel_p)
80 id = id->par_idesc;
81 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
82 return id;
83}
84
85static INLINE const IDESC *
86emit_full16 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
87 int trace_p, int profile_p)
88{
89 const IDESC *id;
90
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);
2f1de745 94 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
4b09af6f
NC
95 return id;
96}
97
98static INLINE const IDESC *
99emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
100 SCACHE *sc, int fast_p)
101{
102 const IDESC *id,*id2;
103
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. */
109
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);
112
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);
115
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);
119
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);
123
124 return id;
125}
126
127static INLINE const IDESC *
128emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
129 SCACHE *sc, int trace_p, int profile_p)
130{
131 const IDESC *id,*id2;
132
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. */
138
139 @cpu@_emit_before (current_cpu, sc, pc, 1);
140
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);
2f1de745 143 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
4b09af6f
NC
144
145 @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
146
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);
2f1de745 149 @cpu@_fill_argbuf_tp (current_cpu, &sc[3].argbuf, trace_p, profile_p);
4b09af6f
NC
150
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);
154
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);
158
159 @cpu@_emit_after (current_cpu, sc + 5, pc);
160
161 return id;
162}
163
164static INLINE const IDESC *
165emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
166 SCACHE *sc, int fast_p)
167{
168 ARGBUF *abuf = &sc->argbuf;
169 const IDESC *id = @cpu@_decode (current_cpu, pc,
170 (USI) insn >> 16, insn, abuf);
171
172 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
173 return id;
174}
175
176static INLINE const IDESC *
177emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
178 int trace_p, int profile_p)
179{
180 const IDESC *id;
181
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);
2f1de745 185 @cpu@_fill_argbuf_tp (current_cpu, &sc[1].argbuf, trace_p, profile_p);
4b09af6f
NC
186 return id;
187}
188
189EOF
190
191;;
192
193xinit)
194
195# Nothing needed.
196
197;;
198
199xextract-pbb)
200
201# Inputs: current_cpu, pc, sc, max_insns, FAST_P
202# Outputs: sc, pc
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.
208
209cat <<EOF
6003fe16 210#line $LINENO "$0"
4b09af6f
NC
211{
212 const IDESC *idesc;
213 int icount = 0;
214
215 if ((pc & 3) != 0)
216 {
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 */
223
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. */
227#if 0
228 if ((insn & 0x8000) != 0
229 && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
230 sim_engine_invalid_insn (current_cpu, pc, 0);
231#endif
232
233 /* Only emit before/after handlers if necessary. */
234 if (FAST_P || (! trace_p && ! profile_p))
235 {
236 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
237 cti_sc = sc;
238 ++sc;
239 --max_insns;
240 }
241 else
242 {
243 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
244 trace_p, profile_p);
245 cti_sc = sc + 1;
246 sc += 3;
247 max_insns -= 3;
248 }
249 ++icount;
250 pc += 2;
251 if (IDESC_CTI_P (idesc))
252 {
253 SET_CTI_VPC (cti_sc);
254 goto Finish;
255 }
256 }
257
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. */
266
267 if (FAST_P)
268 {
269 while (max_insns > 0)
270 {
271 USI insn = GETIMEMUSI (current_cpu, pc);
272 if ((SI) insn < 0)
273 {
274 /* 32 bit insn */
275 idesc = emit_32 (current_cpu, pc, insn, sc, 1);
276 ++sc;
277 --max_insns;
278 ++icount;
279 pc += 4;
280 if (IDESC_CTI_P (idesc))
281 {
282 SET_CTI_VPC (sc - 1);
283 break;
284 }
285 }
286 else
287 {
288 if ((insn & 0x8000) != 0) /* parallel? */
289 {
df2a9ff4
AC
290 int up_count;
291
292 if (((insn >> 16) & 0xfff0) == 0x10f0)
293 {
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 ) */
297 /* insn */
298 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
299 sc, 1, 0);
300 /* trap */
301 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
302 up_count = 2;
303 }
304 else
305 {
306 /* Yep. Here's the "interesting" [sic] part. */
307 idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
308 up_count = 3;
309 }
310 sc += up_count;
311 max_insns -= up_count;
4b09af6f
NC
312 icount += 2;
313 pc += 4;
314 if (IDESC_CTI_P (idesc))
315 {
df2a9ff4 316 SET_CTI_VPC (sc - up_count);
4b09af6f
NC
317 break;
318 }
319 }
320 else /* 2 serial 16 bit insns */
321 {
322 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
323 ++sc;
324 --max_insns;
325 ++icount;
326 pc += 2;
327 if (IDESC_CTI_P (idesc))
328 {
329 SET_CTI_VPC (sc - 1);
330 break;
331 }
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. */
335 if (max_insns == 0)
336 break;
337 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
338 ++sc;
339 --max_insns;
340 ++icount;
341 pc += 2;
342 if (IDESC_CTI_P (idesc))
343 {
344 SET_CTI_VPC (sc - 1);
345 break;
346 }
347 }
348 }
349 }
350 }
351 else /* ! FAST_P */
352 {
353 while (max_insns > 0)
354 {
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 */
359 if ((SI) insn < 0)
360 {
361 /* 32 bit insn
362 Only emit before/after handlers if necessary. */
363 if (trace_p || profile_p)
364 {
365 idesc = emit_full32 (current_cpu, pc, insn, sc,
366 trace_p, profile_p);
367 cti_sc = sc + 1;
368 sc += 3;
369 max_insns -= 3;
370 }
371 else
372 {
373 idesc = emit_32 (current_cpu, pc, insn, sc, 0);
374 cti_sc = sc;
375 ++sc;
376 --max_insns;
377 }
378 ++icount;
379 pc += 4;
380 if (IDESC_CTI_P (idesc))
381 {
382 SET_CTI_VPC (cti_sc);
383 break;
384 }
385 }
386 else
387 {
388 if ((insn & 0x8000) != 0) /* parallel? */
389 {
390 /* Yep. Here's the "interesting" [sic] part.
391 Only emit before/after handlers if necessary. */
392 if (trace_p || profile_p)
393 {
df2a9ff4
AC
394 if (((insn >> 16) & 0xfff0) == 0x10f0)
395 {
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 ) */
399 /* insn */
400 idesc = emit_full16 (current_cpu, pc + 2,
401 insn & 0x7fff, sc, 0, 0);
402 /* trap */
403 emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
404 0, 0);
405 }
406 else
407 {
408 idesc = emit_full_parallel (current_cpu, pc, insn,
409 sc, trace_p, profile_p);
410 }
4b09af6f
NC
411 cti_sc = sc + 1;
412 sc += 6;
413 max_insns -= 6;
414 }
415 else
416 {
df2a9ff4
AC
417 int up_count;
418
419 if (((insn >> 16) & 0xfff0) == 0x10f0)
420 {
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 ) */
424 /* insn */
425 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
426 sc, 0, 0);
427 /* trap */
428 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
429 up_count = 2;
430 }
431 else
432 {
433 idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
434 up_count = 3;
435 }
4b09af6f 436 cti_sc = sc;
df2a9ff4
AC
437 sc += up_count;
438 max_insns -= up_count;
4b09af6f
NC
439 }
440 icount += 2;
441 pc += 4;
442 if (IDESC_CTI_P (idesc))
443 {
444 SET_CTI_VPC (cti_sc);
445 break;
446 }
447 }
448 else /* 2 serial 16 bit insns */
449 {
450 /* Only emit before/after handlers if necessary. */
451 if (trace_p || profile_p)
452 {
453 idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
454 trace_p, profile_p);
455 cti_sc = sc + 1;
456 sc += 3;
457 max_insns -= 3;
458 }
459 else
460 {
461 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
462 cti_sc = sc;
463 ++sc;
464 --max_insns;
465 }
466 ++icount;
467 pc += 2;
468 if (IDESC_CTI_P (idesc))
469 {
470 SET_CTI_VPC (cti_sc);
471 break;
472 }
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. */
476 if (max_insns <= 0)
477 break;
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)
482 {
483 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
484 trace_p, profile_p);
485 cti_sc = sc + 1;
486 sc += 3;
487 max_insns -= 3;
488 }
489 else
490 {
491 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
492 cti_sc = sc;
493 ++sc;
494 --max_insns;
495 }
496 ++icount;
497 pc += 2;
498 if (IDESC_CTI_P (idesc))
499 {
500 SET_CTI_VPC (cti_sc);
501 break;
502 }
503 }
504 }
505 }
506 }
507
508 Finish:
509 SET_INSN_COUNT (icount);
510}
511EOF
512
513;;
514
515xfull-exec-pbb)
516
517# Inputs: current_cpu, vpc, FAST_P
518# Outputs: vpc
519# vpc is the virtual program counter.
520
521cat <<EOF
6003fe16 522#line $LINENO "$0"
4b09af6f
NC
523#define DEFINE_SWITCH
524#include "sem2-switch.c"
525EOF
526
527;;
528
529*)
530 echo "Invalid argument to mainloop.in: $1" >&2
531 exit 1
532 ;;
533
534esac