1 # Simulator main loop for m32r2. -*- C -*-
3 # Copyright 1996, 1997, 1998, 2003, 2004, 2007 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 2, or (at your option)
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 along
18 # with this program; if not, write to the Free Software Foundation, Inc.,
19 # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 # /bin/sh mainloop.in command
28 # extract-{simple,scache,pbb}
29 # {full,fast}-exec-{simple,scache,pbb}
31 # A target need only provide a "full" version of one of simple,scache,pbb.
32 # If the target wants it can also provide a fast version of same, or if
33 # the slow (full featured) version is `simple', then the fast version can be
35 # A target can't provide more than this.
37 # ??? After a few more ports are done, revisit.
38 # 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 sc[1].argbuf.trace_p = trace_p;
95 sc[1].argbuf.profile_p = profile_p;
99 static INLINE const IDESC *
100 emit_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
101 SCACHE *sc, int fast_p)
103 const IDESC *id,*id2;
105 /* Emit both insns, then emit a finisher-upper.
106 We speed things up by handling the second insn serially
107 [not parallelly]. Then the writeback only has to deal
108 with the first insn. */
109 /* ??? Revisit to handle exceptions right. */
111 /* FIXME: No need to handle this parallely if second is nop. */
112 id = emit_16 (current_cpu, pc, insn >> 16, sc, fast_p, 1);
114 /* Note that this can never be a cti. No cti's go in the S pipeline. */
115 id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 1, fast_p, 0);
117 /* Set sc/snc insns notion of where to skip to. */
118 if (IDESC_SKIP_P (id))
119 SEM_SKIP_COMPILE (current_cpu, sc, 1);
121 /* Emit code to finish executing the semantics
122 (write back the results). */
123 emit_par_finish (current_cpu, pc, sc + 2, sc, id, sc + 1, id2);
128 static INLINE const IDESC *
129 emit_full_parallel (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
130 SCACHE *sc, int trace_p, int profile_p)
132 const IDESC *id,*id2;
134 /* Emit both insns, then emit a finisher-upper.
135 We speed things up by handling the second insn serially
136 [not parallelly]. Then the writeback only has to deal
137 with the first insn. */
138 /* ??? Revisit to handle exceptions right. */
140 @cpu@_emit_before (current_cpu, sc, pc, 1);
142 /* FIXME: No need to handle this parallelly if second is nop. */
143 id = emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 1);
144 sc[1].argbuf.trace_p = trace_p;
145 sc[1].argbuf.profile_p = profile_p;
147 @cpu@_emit_before (current_cpu, sc + 2, pc, 0);
149 /* Note that this can never be a cti. No cti's go in the S pipeline. */
150 id2 = emit_16 (current_cpu, pc + 2, insn & 0x7fff, sc + 3, 0, 0);
151 sc[3].argbuf.trace_p = trace_p;
152 sc[3].argbuf.profile_p = profile_p;
154 /* Set sc/snc insns notion of where to skip to. */
155 if (IDESC_SKIP_P (id))
156 SEM_SKIP_COMPILE (current_cpu, sc, 4);
158 /* Emit code to finish executing the semantics
159 (write back the results). */
160 emit_par_finish (current_cpu, pc, sc + 4, sc + 1, id, sc + 3, id2);
162 @cpu@_emit_after (current_cpu, sc + 5, pc);
167 static INLINE const IDESC *
168 emit_32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn,
169 SCACHE *sc, int fast_p)
171 ARGBUF *abuf = &sc->argbuf;
172 const IDESC *id = @cpu@_decode (current_cpu, pc,
173 (USI) insn >> 16, insn, abuf);
175 @cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
179 static INLINE const IDESC *
180 emit_full32 (SIM_CPU *current_cpu, PCADDR pc, CGEN_INSN_INT insn, SCACHE *sc,
181 int trace_p, int profile_p)
185 @cpu@_emit_before (current_cpu, sc, pc, 1);
186 id = emit_32 (current_cpu, pc, insn, sc + 1, 0);
187 @cpu@_emit_after (current_cpu, sc + 2, pc);
188 sc[1].argbuf.trace_p = trace_p;
189 sc[1].argbuf.profile_p = profile_p;
205 # Inputs: current_cpu, pc, sc, max_insns, FAST_P
207 # sc must be left pointing past the last created entry.
208 # pc must be left pointing past the last created entry.
209 # If the pbb is terminated by a cti insn, SET_CTI_VPC(sc) must be called
210 # to record the vpc of the cti insn.
211 # SET_INSN_COUNT(n) must be called to record number of real insns.
220 /* This occurs when single stepping and when compiling the not-taken
221 part of conditional branches. */
222 UHI insn = GETIMEMUHI (current_cpu, pc);
223 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
224 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
225 SCACHE *cti_sc; /* ??? tmp hack */
227 /* A parallel insn isn't allowed here, but we don't mind nops.
228 ??? We need to wait until the insn is executed before signalling
229 the error, for situations where such signalling is wanted. */
231 if ((insn & 0x8000) != 0
232 && (insn & 0x7fff) != 0x7000) /* parallel nops are ok */
233 sim_engine_invalid_insn (current_cpu, pc, 0);
236 /* Only emit before/after handlers if necessary. */
237 if (FAST_P || (! trace_p && ! profile_p))
239 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, FAST_P, 0);
246 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
254 if (IDESC_CTI_P (idesc))
256 SET_CTI_VPC (cti_sc);
261 /* There are two copies of the compiler: full(!fast) and fast.
262 The "full" case emits before/after handlers for each insn.
263 Having two copies of this code is a tradeoff, having one copy
264 seemed a bit more difficult to read (due to constantly testing
265 FAST_P). ??? On the other hand, with address ranges we'll want to
266 omit before/after handlers for unwanted insns. Having separate loops
267 for FAST/!FAST avoids constantly doing the test in the loop, but
268 typically FAST_P is a constant and such tests will get optimized out. */
272 while (max_insns > 0)
274 USI insn = GETIMEMUSI (current_cpu, pc);
278 idesc = emit_32 (current_cpu, pc, insn, sc, 1);
283 if (IDESC_CTI_P (idesc))
285 SET_CTI_VPC (sc - 1);
291 if ((insn & 0x8000) != 0) /* parallel? */
295 if (((insn >> 16) & 0xfff0) == 0x10f0)
297 /* FIXME: No need to handle this sequentially if system
298 calls will be able to execute after second insn in
299 parallel. ( trap #num || insn ) */
301 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
304 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 1, 0);
309 /* Yep. Here's the "interesting" [sic] part. */
310 idesc = emit_parallel (current_cpu, pc, insn, sc, 1);
314 max_insns -= up_count;
317 if (IDESC_CTI_P (idesc))
319 SET_CTI_VPC (sc - up_count);
323 else /* 2 serial 16 bit insns */
325 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 1, 0);
330 if (IDESC_CTI_P (idesc))
332 SET_CTI_VPC (sc - 1);
335 /* While we're guaranteed that there's room to extract the
336 insn, when single stepping we can't; the pbb must stop
337 after the first insn. */
340 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 1, 0);
345 if (IDESC_CTI_P (idesc))
347 SET_CTI_VPC (sc - 1);
356 while (max_insns > 0)
358 USI insn = GETIMEMUSI (current_cpu, pc);
359 int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
360 int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
361 SCACHE *cti_sc; /* ??? tmp hack */
365 Only emit before/after handlers if necessary. */
366 if (trace_p || profile_p)
368 idesc = emit_full32 (current_cpu, pc, insn, sc,
376 idesc = emit_32 (current_cpu, pc, insn, sc, 0);
383 if (IDESC_CTI_P (idesc))
385 SET_CTI_VPC (cti_sc);
391 if ((insn & 0x8000) != 0) /* parallel? */
393 /* Yep. Here's the "interesting" [sic] part.
394 Only emit before/after handlers if necessary. */
395 if (trace_p || profile_p)
397 if (((insn >> 16) & 0xfff0) == 0x10f0)
399 /* FIXME: No need to handle this sequentially if
400 system calls will be able to execute after second
401 insn in parallel. ( trap #num || insn ) */
403 idesc = emit_full16 (current_cpu, pc + 2,
404 insn & 0x7fff, sc, 0, 0);
406 emit_full16 (current_cpu, pc, insn >> 16, sc + 3,
411 idesc = emit_full_parallel (current_cpu, pc, insn,
412 sc, trace_p, profile_p);
422 if (((insn >> 16) & 0xfff0) == 0x10f0)
424 /* FIXME: No need to handle this sequentially if
425 system calls will be able to execute after second
426 insn in parallel. ( trap #num || insn ) */
428 idesc = emit_16 (current_cpu, pc + 2, insn & 0x7fff,
431 emit_16 (current_cpu, pc, insn >> 16, sc + 1, 0, 0);
436 idesc = emit_parallel (current_cpu, pc, insn, sc, 0);
441 max_insns -= up_count;
445 if (IDESC_CTI_P (idesc))
447 SET_CTI_VPC (cti_sc);
451 else /* 2 serial 16 bit insns */
453 /* Only emit before/after handlers if necessary. */
454 if (trace_p || profile_p)
456 idesc = emit_full16 (current_cpu, pc, insn >> 16, sc,
464 idesc = emit_16 (current_cpu, pc, insn >> 16, sc, 0, 0);
471 if (IDESC_CTI_P (idesc))
473 SET_CTI_VPC (cti_sc);
476 /* While we're guaranteed that there's room to extract the
477 insn, when single stepping we can't; the pbb must stop
478 after the first insn. */
481 /* Use the same trace/profile address for the 2nd insn.
482 Saves us having to compute it and they come in pairs
483 anyway (e.g. can never branch to the 2nd insn). */
484 if (trace_p || profile_p)
486 idesc = emit_full16 (current_cpu, pc, insn & 0x7fff, sc,
494 idesc = emit_16 (current_cpu, pc, insn & 0x7fff, sc, 0, 0);
501 if (IDESC_CTI_P (idesc))
503 SET_CTI_VPC (cti_sc);
512 SET_INSN_COUNT (icount);
520 # Inputs: current_cpu, vpc, FAST_P
522 # vpc is the virtual program counter.
525 #define DEFINE_SWITCH
526 #include "sem2-switch.c"
532 echo "Invalid argument to mainloop.in: $1" >&2