xref: /netbsd-src/external/gpl3/gdb/dist/sim/common/cgen-engine.h (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /* Engine header for Cpu tools GENerated simulators.
2    Copyright (C) 1998, 1999, 2007, 2008, 2009, 2010, 2011
3    Free Software Foundation, Inc.
4    Contributed by Cygnus Support.
5 
6 This file is part of GDB, the GNU debugger.
7 
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 /* This file is included by ${cpu}.h.
22    It needs CGEN_INSN_WORD which is defined by ${cpu}.h.
23    ??? A lot of this could be moved to genmloop.sh to be put in eng.h
24    and thus remove some conditional compilation.  We'd still need
25    CGEN_INSN_WORD though.  */
26 
27 /* Semantic functions come in six versions on two axes:
28    fast/full-featured, and using one of the simple/scache/compilation engines.
29    A full featured simulator is always provided.  --enable-sim-fast includes
30    support for fast execution by duplicating the semantic code but leaving
31    out all features like tracing and profiling.
32    Using the scache is selected with --enable-sim-scache.  */
33 /* FIXME: --enable-sim-fast not implemented yet.  */
34 /* FIXME: undecided how to handle WITH_SCACHE_PBB.  */
35 
36 /* There are several styles of engines, all generally supported by the
37    same code:
38 
39    WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching
40    WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis
41    !WITH_SCACHE - simple engine: fetch an insn, execute an insn
42 
43    The !WITH_SCACHE case can also be broken up into two flavours:
44    extract the fields of the insn into an ARGBUF struct, or defer the
45    extraction to the semantic handler.  The former can be viewed as the
46    WITH_SCACHE case with a cache size of 1 (thus there's no need for a
47    WITH_EXTRACTION macro).  The WITH_SCACHE case always extracts the fields
48    into an ARGBUF struct.  */
49 
50 #ifndef CGEN_ENGINE_H
51 #define CGEN_ENGINE_H
52 
53 /* Instruction field support macros.  */
54 
55 #define EXTRACT_MSB0_SINT(val, total, start, length) \
56 (((INT) (val) << ((sizeof (INT) * 8) - (total) + (start))) \
57  >> ((sizeof (INT) * 8) - (length)))
58 #define EXTRACT_MSB0_UINT(val, total, start, length) \
59 (((UINT) (val) << ((sizeof (UINT) * 8) - (total) + (start))) \
60  >> ((sizeof (UINT) * 8) - (length)))
61 
62 #define EXTRACT_LSB0_SINT(val, total, start, length) \
63 (((INT) (val) << ((sizeof (INT) * 8) - (start) - 1)) \
64  >> ((sizeof (INT) * 8) - (length)))
65 #define EXTRACT_LSB0_UINT(val, total, start, length) \
66 (((UINT) (val) << ((sizeof (UINT) * 8) - (start) - 1)) \
67  >> ((sizeof (UINT) * 8) - (length)))
68 
69 #define EXTRACT_MSB0_LGSINT(val, total, start, length) \
70 (((CGEN_INSN_LGSINT) (val) << ((sizeof (CGEN_INSN_LGSINT) * 8) - (total) + (start))) \
71  >> ((sizeof (CGEN_INSN_LGSINT) * 8) - (length)))
72 #define EXTRACT_MSB0_LGUINT(val, total, start, length) \
73 (((CGEN_INSN_UINT) (val) << ((sizeof (CGEN_INSN_LGUINT) * 8) - (total) + (start))) \
74  >> ((sizeof (CGEN_INSN_LGUINT) * 8) - (length)))
75 
76 #define EXTRACT_LSB0_LGSINT(val, total, start, length) \
77 (((CGEN_INSN_LGSINT) (val) << ((sizeof (CGEN_INSN_LGSINT) * 8) - (start) - 1)) \
78  >> ((sizeof (CGEN_INSN_LGSINT) * 8) - (length)))
79 #define EXTRACT_LSB0_LGUINT(val, total, start, length) \
80 (((CGEN_INSN_LGUINT) (val) << ((sizeof (CGEN_INSN_LGUINT) * 8) - (start) - 1)) \
81  >> ((sizeof (CGEN_INSN_LGUINT) * 8) - (length)))
82 
83 /* Semantic routines.  */
84 
85 /* Type of the machine generated extraction fns.  */
86 /* ??? No longer used.  */
87 typedef void (EXTRACT_FN) (SIM_CPU *, IADDR, CGEN_INSN_WORD, ARGBUF *);
88 
89 /* Type of the machine generated semantic fns.  */
90 
91 #if WITH_SCACHE
92 
93 /* Instruction fields are extracted into ARGBUF before calling the
94    semantic routine.  */
95 #if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_GENWRITE
96 typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *);
97 #else
98 typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG);
99 #endif
100 
101 #else
102 
103 /* Result of semantic routines is a status indicator (wip).  */
104 typedef unsigned int SEM_STATUS;
105 
106 /* Instruction fields are extracted by the semantic routine.
107    ??? TODO: multi word insns.  */
108 #if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_GENWRITE
109 typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *, CGEN_INSN_WORD);
110 #else
111 typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, CGEN_INSN_WORD);
112 #endif
113 
114 #endif
115 
116 /* In the ARGBUF struct, a pointer to the semantic routine for the insn.  */
117 
118 union sem {
119 #if ! WITH_SEM_SWITCH_FULL
120   SEMANTIC_FN *sem_full;
121 #endif
122 #if ! WITH_SEM_SWITCH_FAST
123   SEMANTIC_FN *sem_fast;
124 #endif
125 #if WITH_SEM_SWITCH_FULL || WITH_SEM_SWITCH_FAST
126 #ifdef __GNUC__
127   void *sem_case;
128 #else
129   int sem_case;
130 #endif
131 #endif
132 };
133 
134 /* Set the appropriate semantic handler in ABUF.  */
135 
136 #if WITH_SEM_SWITCH_FULL
137 #ifdef __GNUC__
138 #define SEM_SET_FULL_CODE(abuf, idesc) \
139   do { (abuf)->semantic.sem_case = (idesc)->sem_full_lab; } while (0)
140 #else
141 #define SEM_SET_FULL_CODE(abuf, idesc) \
142   do { (abuf)->semantic.sem_case = (idesc)->num; } while (0)
143 #endif
144 #else
145 #define SEM_SET_FULL_CODE(abuf, idesc) \
146   do { (abuf)->semantic.sem_full = (idesc)->sem_full; } while (0)
147 #endif
148 
149 #if WITH_SEM_SWITCH_FAST
150 #ifdef __GNUC__
151 #define SEM_SET_FAST_CODE(abuf, idesc) \
152   do { (abuf)->semantic.sem_case = (idesc)->sem_fast_lab; } while (0)
153 #else
154 #define SEM_SET_FAST_CODE(abuf, idesc) \
155   do { (abuf)->semantic.sem_case = (idesc)->num; } while (0)
156 #endif
157 #else
158 #define SEM_SET_FAST_CODE(abuf, idesc) \
159   do { (abuf)->semantic.sem_fast = (idesc)->sem_fast; } while (0)
160 #endif
161 
162 #define SEM_SET_CODE(abuf, idesc, fast_p) \
163 do { \
164   if (fast_p) \
165     SEM_SET_FAST_CODE ((abuf), (idesc)); \
166   else \
167     SEM_SET_FULL_CODE ((abuf), (idesc)); \
168 } while (0)
169 
170 /* Return non-zero if IDESC is a conditional or unconditional CTI.  */
171 
172 #define IDESC_CTI_P(idesc) \
173      ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \
174        & (CGEN_ATTR_MASK (CGEN_INSN_COND_CTI) \
175 	  | CGEN_ATTR_MASK (CGEN_INSN_UNCOND_CTI))) \
176       != 0)
177 
178 /* Return non-zero if IDESC is a skip insn.  */
179 
180 #define IDESC_SKIP_P(idesc) \
181      ((CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) \
182        & CGEN_ATTR_MASK (CGEN_INSN_SKIP_CTI)) \
183       != 0)
184 
185 /* Return pointer to ARGBUF given ptr to SCACHE.  */
186 #define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf)
187 
188 #if WITH_SCACHE
189 
190 #define CIA_ADDR(cia) (cia)
191 
192 #if WITH_SCACHE_PBB
193 
194 /* Return the scache pointer of the current insn.  */
195 #define SEM_SEM_ARG(vpc, sc) (vpc)
196 
197 /* Return the virtual pc of the next insn to execute
198    (assuming this isn't a cti or the branch isn't taken).  */
199 #define SEM_NEXT_VPC(sem_arg, pc, len) ((sem_arg) + 1)
200 
201 /* Update the instruction counter.  */
202 #define PBB_UPDATE_INSN_COUNT(cpu,sc) \
203   (CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count)
204 
205 /* Do not append a `;' to invocations of this.
206    npc,br_type are for communication between the cti insn and cti-chain.  */
207 #define SEM_BRANCH_INIT \
208   IADDR npc = 0; /* assign a value for -Wall */ \
209   SEM_BRANCH_TYPE br_type = SEM_BRANCH_UNTAKEN;
210 
211 /* SEM_IN_SWITCH is defined at the top of the mainloop.c files
212    generated by genmloop.sh.  It exists so generated semantic code needn't
213    care whether it's being put in a switch or in a function.  */
214 #ifdef SEM_IN_SWITCH
215 #define SEM_BRANCH_FINI(pcvar) \
216 do { \
217   pbb_br_npc = npc; \
218   pbb_br_type = br_type; \
219 } while (0)
220 #else /* 1 semantic function per instruction */
221 #define SEM_BRANCH_FINI(pcvar) \
222 do { \
223   CPU_PBB_BR_NPC (current_cpu) = npc; \
224   CPU_PBB_BR_TYPE (current_cpu) = br_type; \
225 } while (0)
226 #endif
227 
228 #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
229 do { \
230   npc = (newval); \
231   br_type = SEM_BRANCH_CACHEABLE; \
232 } while (0)
233 
234 #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
235 do { \
236   npc = (newval); \
237   br_type = SEM_BRANCH_UNCACHEABLE; \
238 } while (0)
239 
240 #define SEM_SKIP_COMPILE(cpu, sc, skip) \
241 do { \
242   SEM_ARGBUF (sc) -> skip_count = (skip); \
243 } while (0)
244 
245 #define SEM_SKIP_INSN(cpu, sc, vpcvar) \
246 do { \
247   (vpcvar) += SEM_ARGBUF (sc) -> skip_count; \
248 } while (0)
249 
250 #else /* ! WITH_SCACHE_PBB */
251 
252 #define SEM_SEM_ARG(vpc, sc) (sc)
253 
254 #define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
255 
256 /* ??? May wish to move taken_p out of here and make it explicit.  */
257 #define SEM_BRANCH_INIT \
258   int taken_p = 0;
259 
260 #ifndef TARGET_SEM_BRANCH_FINI
261 #define TARGET_SEM_BRANCH_FINI(pcvar, taken_p)
262 #endif
263 #define SEM_BRANCH_FINI(pcvar) \
264   do { TARGET_SEM_BRANCH_FINI (pcvar, taken_p); } while (0)
265 
266 #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
267 do { \
268   (pcvar) = (newval); \
269   taken_p = 1; \
270 } while (0)
271 
272 #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
273 do { \
274   (pcvar) = (newval); \
275   taken_p = 1; \
276 } while (0)
277 
278 #endif /* ! WITH_SCACHE_PBB */
279 
280 #else /* ! WITH_SCACHE */
281 
282 /* This is the "simple" engine case.  */
283 
284 #define CIA_ADDR(cia) (cia)
285 
286 #define SEM_SEM_ARG(vpc, sc) (sc)
287 
288 #define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
289 
290 #define SEM_BRANCH_INIT \
291   int taken_p = 0;
292 
293 #define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar) \
294 do { \
295   (pcvar) = (newval); \
296   taken_p = 1; \
297 } while (0)
298 
299 #define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \
300 do { \
301   (pcvar) = (newval); \
302   taken_p = 1; \
303 } while (0)
304 
305 /* Finish off branch insns.
306    The target must define TARGET_SEM_BRANCH_FINI.
307    ??? This can probably go away when define-execute is finished.  */
308 #define SEM_BRANCH_FINI(pcvar, bool_attrs) \
309   do { TARGET_SEM_BRANCH_FINI ((pcvar), (bool_attrs), taken_p); } while (0)
310 
311 /* Finish off non-branch insns.
312    The target must define TARGET_SEM_NBRANCH_FINI.
313    ??? This can probably go away when define-execute is finished.  */
314 #define SEM_NBRANCH_FINI(pcvar, bool_attrs) \
315   do { TARGET_SEM_NBRANCH_FINI ((pcvar), (bool_attrs)); } while (0)
316 
317 #endif /* ! WITH_SCACHE */
318 
319 /* Instruction information.  */
320 
321 /* Sanity check, at most one of these may be true.  */
322 #if WITH_PARALLEL_READ + WITH_PARALLEL_WRITE + WITH_PARALLEL_GENWRITE > 1
323 #error "At most one of WITH_PARALLEL_{READ,WRITE,GENWRITE} can be true."
324 #endif
325 
326 /* Compile time computable instruction data.  */
327 
328 struct insn_sem {
329   /* The instruction type (a number that identifies each insn over the
330      entire architecture).  */
331   CGEN_INSN_TYPE type;
332 
333   /* Index in IDESC table.  */
334   int index;
335 
336   /* Semantic format number.  */
337   int sfmt;
338 
339 #if HAVE_PARALLEL_INSNS && ! WITH_PARALLEL_ONLY
340   /* Index in IDESC table of parallel handler.  */
341   int par_index;
342 #endif
343 
344 #if WITH_PARALLEL_READ
345   /* Index in IDESC table of read handler.  */
346   int read_index;
347 #endif
348 
349 #if WITH_PARALLEL_WRITE
350   /* Index in IDESC table of writeback handler.  */
351   int write_index;
352 #endif
353 };
354 
355 /* Entry in semantic function table.
356    This information is copied to the insn descriptor table at run-time.  */
357 
358 struct sem_fn_desc {
359   /* Index in IDESC table.  */
360   int index;
361 
362   /* Function to perform the semantics of the insn.  */
363   SEMANTIC_FN *fn;
364 };
365 
366 /* Run-time computed instruction descriptor.  */
367 
368 struct idesc {
369 #if WITH_SEM_SWITCH_FAST
370 #ifdef __GNUC__
371   void *sem_fast_lab;
372 #else
373   /* nothing needed, switch's on `num' member */
374 #endif
375 #else
376   SEMANTIC_FN *sem_fast;
377 #endif
378 
379 #if WITH_SEM_SWITCH_FULL
380 #ifdef __GNUC__
381   void *sem_full_lab;
382 #else
383   /* nothing needed, switch's on `num' member */
384 #endif
385 #else
386   SEMANTIC_FN *sem_full;
387 #endif
388 
389   /* Parallel support.  */
390 #if HAVE_PARALLEL_INSNS && (! WITH_PARALLEL_ONLY || (WITH_PARALLEL_ONLY && ! WITH_PARALLEL_GENWRITE))
391   /* Pointer to parallel handler if serial insn.
392      Pointer to readahead/writeback handler if parallel insn.  */
393   struct idesc *par_idesc;
394 #endif
395 
396   /* Instruction number (index in IDESC table, profile table).
397      Also used to switch on in non-gcc semantic switches.  */
398   int num;
399 
400   /* Semantic format id.  */
401   int sfmt;
402 
403   /* instruction data (name, attributes, size, etc.) */
404   const CGEN_INSN *idata;
405 
406   /* instruction attributes, copied from `idata' for speed */
407   const CGEN_INSN_ATTR_TYPE *attrs;
408 
409   /* instruction length in bytes, copied from `idata' for speed */
410   int length;
411 
412   /* profiling/modelling support */
413   const INSN_TIMING *timing;
414 };
415 
416 /* Tracing/profiling.  */
417 
418 /* Return non-zero if a before/after handler is needed.
419    When tracing/profiling a selected range there's no need to slow
420    down simulation of the other insns (except to get more accurate data!).
421 
422    ??? May wish to profile all insns if doing insn tracing, or to
423    get more accurate cycle data.
424 
425    First test ANY_P so we avoid a potentially expensive HIT_P call
426    [if there are lots of address ranges].  */
427 
428 #define PC_IN_TRACE_RANGE_P(cpu, pc) \
429   (TRACE_ANY_P (cpu) \
430    && ADDR_RANGE_HIT_P (TRACE_RANGE (CPU_TRACE_DATA (cpu)), (pc)))
431 #define PC_IN_PROFILE_RANGE_P(cpu, pc) \
432   (PROFILE_ANY_P (cpu) \
433    && ADDR_RANGE_HIT_P (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), (pc)))
434 
435 #endif /* CGEN_ENGINE_H */
436