import gdb-1999-06-28 snapshot
[deliverable/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 /* These are used so that we can compile two copies of the semantic code,
184 one with full feature support and one without that runs fast(er). */
185 #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
186 #define SEMF_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
187
188 /* Return pointer to ARGBUF given ptr to SCACHE. */
189 #define SEM_ARGBUF(sem_arg) (& (sem_arg) -> argbuf)
190
191 /* There are several styles of engines, all generally supported by the
192 same code:
193
194 WITH_SCACHE && WITH_SCACHE_PBB - pseudo-basic-block scaching
195 WITH_SCACHE && !WITH_SCACHE_PBB - scaching on an insn by insn basis
196 !WITH_SCACHE - simple engine: fetch an insn, execute an insn
197
198 ??? The !WITH_SCACHE case can also be broken up into two flavours:
199 extract the fields of the insn into an ARGBUF struct, or defer the
200 extraction to the semantic handler. The WITH_SCACHE case always
201 extracts the fields into an ARGBUF struct. */
202
203 #if WITH_SCACHE
204
205 #define CIA_ADDR(cia) (cia)
206
207 #if WITH_SCACHE_PBB
208
209 /* Return the scache pointer of the current insn. */
210 #define SEM_SEM_ARG(vpc, sc) (vpc)
211
212 /* Return the virtual pc of the next insn to execute
213 (assuming this isn't a cti or the branch isn't taken). */
214 #define SEM_NEXT_VPC(sem_arg, pc, len) ((sem_arg) + 1)
215
216 /* Update the instruction counter. */
217 #define PBB_UPDATE_INSN_COUNT(cpu,sc) \
218 (CPU_INSN_COUNT (cpu) += SEM_ARGBUF (sc) -> fields.chain.insn_count)
219
220 /* Value for br_addr_ptr indicating branch wasn't taken. */
221 #define SEM_BRANCH_UNTAKEN ((SEM_PC *) 0)
222
223 /* Value for br_addr_ptr indicating branch was taken to uncacheable
224 address (e.g. j reg). */
225 #define SEM_BRANCH_UNCACHEABLE ((SEM_PC *) 1)
226
227 /* Initialize next-pbb link for SEM_BRANCH_VIA_CACHE. */
228 #define SEM_BRANCH_INIT_EXTRACT(abuf) \
229 do { (abuf)->fields.cti.addr_cache = 0; } while (0)
230
231 /* Do not append a `;' to invocations of this.
232 npc,npc_ptr are for communication between the cti insn and cti-chain. */
233 #define SEM_BRANCH_INIT \
234 IADDR npc = 0; /* assign a value for -Wall */ \
235 SEM_PC *npc_ptr = SEM_BRANCH_UNTAKEN;
236
237 /* SEM_IN_SWITCH is defined at the top of the mainloop.c files
238 generated by genmloop.sh. It exists so generated semantic code needn't
239 care whether it's being put in a switch or in a function. */
240 #ifdef SEM_IN_SWITCH
241 #define SEM_BRANCH_FINI(pcvar) \
242 do { \
243 pbb_br_npc = npc; \
244 pbb_br_npc_ptr = npc_ptr; \
245 } while (0)
246 #else /* 1 semantic function per instruction */
247 #define SEM_BRANCH_FINI(pcvar) \
248 do { \
249 CPU_PBB_BR_NPC (current_cpu) = npc; \
250 CPU_PBB_BR_NPC_PTR (current_cpu) = npc_ptr; \
251 } while (0)
252 #endif
253
254 /* Return address of cached branch address value. */
255 #define SEM_BRANCH_ADDR_CACHE(sem_arg) \
256 (& SEM_ARGBUF (sem_arg)->fields.cti.addr_cache)
257
258 #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevarptr) \
259 do { \
260 npc = (newval); \
261 npc_ptr = (cachevarptr); \
262 } while (0)
263
264 #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
265 do { \
266 npc = (newval); \
267 npc_ptr = SEM_BRANCH_UNCACHEABLE; \
268 } while (0)
269
270 #else /* ! WITH_SCACHE_PBB */
271
272 #define SEM_SEM_ARG(vpc, sc) (sc)
273
274 #define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
275
276 #define SEM_BRANCH_INIT_EXTRACT(abuf) do { } while (0)
277
278 /* ??? May wish to move taken_p out of here and make it explicit. */
279 #define SEM_BRANCH_INIT \
280 int taken_p = 0;
281
282 #ifndef TARGET_SEM_BRANCH_FINI
283 #define TARGET_SEM_BRANCH_FINI(pcvar, taken_p)
284 #endif
285 #define SEM_BRANCH_FINI(pcvar) \
286 do { TARGET_SEM_BRANCH_FINI (pcvar, taken_p); } while (0)
287
288 #define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used
289
290 #define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar, cachevar) \
291 do { \
292 (pcvar) = (newval); \
293 taken_p = 1; \
294 } while (0)
295
296 #define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
297 do { \
298 (pcvar) = (newval); \
299 taken_p = 1; \
300 } while (0)
301
302 #endif /* ! WITH_SCACHE_PBB */
303
304 #else /* ! WITH_SCACHE */
305
306 /* This is the "simple" engine case. */
307
308 #define CIA_ADDR(cia) (cia)
309
310 #define SEM_SEM_ARG(vpc, sc) (sc)
311
312 #define SEM_NEXT_VPC(sem_arg, pc, len) ((pc) + (len))
313
314 #define SEM_BRANCH_INIT \
315 int taken_p = 0;
316
317 #define SEM_BRANCH_ADDR_CACHE(sem_arg) shouldnt_be_used
318
319 #define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar, cachevar) \
320 do { \
321 (pcvar) = (newval); \
322 taken_p = 1; \
323 } while (0)
324
325 #define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \
326 do { \
327 (pcvar) = (newval); \
328 taken_p = 1; \
329 } while (0)
330
331 /* Finish off branch insns.
332 The target must define TARGET_SEM_BRANCH_FINI.
333 ??? This can probably go away when define-execute is finished. */
334 #define SEM_BRANCH_FINI(pcvar, bool_attrs) \
335 do { TARGET_SEM_BRANCH_FINI ((pcvar), (bool_attrs), taken_p); } while (0)
336
337 /* Finish off non-branch insns.
338 The target must define TARGET_SEM_NBRANCH_FINI.
339 ??? This can probably go away when define-execute is finished. */
340 #define SEM_NBRANCH_FINI(pcvar, bool_attrs) \
341 do { TARGET_SEM_NBRANCH_FINI ((pcvar), (bool_attrs)); } while (0)
342
343 #endif /* ! WITH_SCACHE */
344 \f
345 /* Instruction information. */
346
347 /* Compile time computable instruction data.
348
349 ??? May wish to move parallel execution support into its own struct.
350 It's a fair bit of "clutter" for the "normal" case. */
351
352 struct insn_sem {
353 /* The instruction type (a number that identifies each insn over the
354 entire architecture). */
355 CGEN_INSN_TYPE type;
356
357 /* Index in IDESC table. */
358 int index;
359
360 /* Sanity check, at most one of these may be true. */
361 #if WITH_PARALLEL_READ && WITH_PARALLEL_WRITE
362 #error "Both WITH_PARALLEL_READ && WITH_PARALLEL_WRITE can't be true."
363 #endif
364
365 #if WITH_PARALLEL_READ || WITH_PARALLEL_WRITE
366 /* Index in IDESC table of parallel handler. */
367 int par_index;
368 #endif
369
370 #if WITH_PARALLEL_READ
371 #ifndef __GNUC__
372 /* Semantic format number of pre-read handler.
373 Only used by chips that support parallel execution of several insns.
374 It is always implemented as a `switch'. In the case of GNUC we use
375 computed gotos. When not GNUC, this is the argument to `switch'. */
376 int fmt;
377 #endif
378 #endif
379
380 #if WITH_PARALLEL_WRITE
381 /* Index in IDESC table of writeback handler.
382 Only used by chips that support parallel execution of several insns. */
383 int write_index;
384 #endif
385
386 /* Routines to execute the insn.
387 The full version has all features (profiling,tracing) compiled in.
388 The fast version has none of that. */
389 #if ! WITH_SEM_SWITCH_FULL
390 SEMANTIC_FN *sem_full;
391 #endif
392 #if WITH_FAST && ! WITH_SEM_SWITCH_FAST
393 SEMANTIC_FN *sem_fast;
394 #endif
395 };
396
397 /* Run-time computed instruction descriptor. */
398
399 struct idesc {
400 /* Parallel read-before-exec support. */
401 #if WITH_PARALLEL_READ
402 struct idesc *par_idesc;
403 #ifdef __GNUC__
404 void *read;
405 #else
406 int fmt;
407 #endif
408 #endif
409
410 /* Parallel write-after-exec support. */
411 #if WITH_PARALLEL_WRITE
412 /* Pointer to parallel handler if serial insn.
413 Pointer to writeback handler if parallel insn. */
414 struct idesc *par_idesc;
415 #endif
416
417 #if WITH_SEM_SWITCH_FULL
418 #ifdef __GNUC__
419 void *sem_full_lab;
420 #else
421 /* nothing needed, switch's on `num' member */
422 #endif
423 #else
424 SEMANTIC_FN *sem_full;
425 #endif
426
427 #if WITH_SEM_SWITCH_FAST
428 #ifdef __GNUC__
429 void *sem_fast_lab;
430 #else
431 /* nothing needed, switch's on `num' member */
432 #endif
433 #else
434 SEMANTIC_FN *sem_fast;
435 #endif
436
437 /* Instruction number (index in IDESC table, profile table).
438 Also used to switch on in non-gcc semantic switches. */
439 int num;
440
441 /* instruction data (name, attributes, size, etc.) */
442 const CGEN_INSN *idata;
443
444 /* instruction attributes, copied from `idata' for speed */
445 const CGEN_INSN_ATTR_TYPE *attrs;
446
447 /* instruction length in bytes, copied from `idata' for speed */
448 int length;
449
450 /* profiling/modelling support */
451 const INSN_TIMING *timing;
452 };
453 \f
454 /* Tracing/profiling. */
455
456 /* Return non-zero if a before/after handler is needed.
457 When tracing/profiling a selected range there's no need to slow
458 down simulation of the other insns (except to get more accurate data!).
459
460 ??? May wish to profile all insns if doing insn tracing, or to
461 get more accurate cycle data.
462
463 First test ANY_P so we avoid a potentially expensive HIT_P call
464 [if there are lots of address ranges]. */
465
466 #define PC_IN_TRACE_RANGE_P(cpu, pc) \
467 (TRACE_ANY_P (cpu) \
468 && ADDR_RANGE_HIT_P (TRACE_RANGE (CPU_TRACE_DATA (cpu)), (pc)))
469 #define PC_IN_PROFILE_RANGE_P(cpu, pc) \
470 (PROFILE_ANY_P (cpu) \
471 && ADDR_RANGE_HIT_P (PROFILE_RANGE (CPU_PROFILE_DATA (cpu)), (pc)))
472
473 #endif /* CGEN_ENGINE_H */
This page took 0.043859 seconds and 4 git commands to generate.