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