]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/common/cgen-engine.h
Update copyright notices to add year 2010.
[thirdparty/binutils-gdb.git] / sim / common / cgen-engine.h
1 /* Engine header for Cpu tools GENerated simulators.
2 Copyright (C) 1998, 1999, 2007, 2008, 2009, 2010
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 \f
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 \f
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 \f
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 \f
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 */