import gdb-1999-08-09 snapshot
[deliverable/binutils-gdb.git] / sim / common / cgen-engine.h
CommitLineData
c906108c
SS
1/* Engine header for Cpu tools GENerated simulators.
2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3 Contributed by Cygnus Support.
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 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. */
85typedef 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
94typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *);
95#else
96typedef SEM_PC (SEMANTIC_FN) (SIM_CPU *, SEM_ARG);
97#endif
98
99#else
100
101/* Result of semantic routines is a status indicator (wip). */
102typedef unsigned int SEM_STATUS;
103
104/* Instruction fields are extracted by the semantic routine.
105 ??? TODO: multi word insns. */
106#if HAVE_PARALLEL_INSNS
107typedef SEM_STATUS (SEMANTIC_FN) (SIM_CPU *, SEM_ARG, PAREXEC *, CGEN_INSN_INT);
108#else
109typedef 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
116union 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) \
161do { \
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
c906108c
SS
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
c906108c 215/* Do not append a `;' to invocations of this.
96baa820 216 npc,br_type are for communication between the cti insn and cti-chain. */
c906108c
SS
217#define SEM_BRANCH_INIT \
218 IADDR npc = 0; /* assign a value for -Wall */ \
96baa820 219 SEM_BRANCH_TYPE br_type = SEM_BRANCH_UNTAKEN;
c906108c
SS
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) \
226do { \
227 pbb_br_npc = npc; \
96baa820 228 pbb_br_type = br_type; \
c906108c
SS
229} while (0)
230#else /* 1 semantic function per instruction */
231#define SEM_BRANCH_FINI(pcvar) \
232do { \
233 CPU_PBB_BR_NPC (current_cpu) = npc; \
96baa820 234 CPU_PBB_BR_TYPE (current_cpu) = br_type; \
c906108c
SS
235} while (0)
236#endif
237
96baa820 238#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
c906108c
SS
239do { \
240 npc = (newval); \
96baa820 241 br_type = SEM_BRANCH_CACHEABLE; \
c906108c
SS
242} while (0)
243
244#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
245do { \
246 npc = (newval); \
96baa820
JM
247 br_type = SEM_BRANCH_UNCACHEABLE; \
248} while (0)
249
250#define SEM_SKIP_COMPILE(cpu, sc, skip) \
251do { \
252 SEM_ARGBUF (sc) -> skip_count = (skip); \
253} while (0)
254
255#define SEM_SKIP_INSN(cpu, sc, vpcvar) \
256do { \
257 (vpcvar) += SEM_ARGBUF (sc) -> skip_count; \
c906108c
SS
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
c906108c
SS
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
085dd6e6 270#ifndef TARGET_SEM_BRANCH_FINI
c906108c
SS
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
96baa820 276#define SEM_BRANCH_VIA_CACHE(cpu, sc, newval, pcvar) \
c906108c
SS
277do { \
278 (pcvar) = (newval); \
279 taken_p = 1; \
280} while (0)
281
282#define SEM_BRANCH_VIA_ADDR(cpu, sc, newval, pcvar) \
283do { \
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
96baa820 303#define SEM_BRANCH_VIA_CACHE(cpu, abuf, newval, pcvar) \
c906108c
SS
304do { \
305 (pcvar) = (newval); \
306 taken_p = 1; \
307} while (0)
308
309#define SEM_BRANCH_VIA_ADDR(cpu, abuf, newval, pcvar) \
310do { \
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
96baa820
JM
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
c906108c 335
96baa820 336/* Compile time computable instruction data. */
c906108c
SS
337
338struct 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
96baa820
JM
346 /* Semantic format number. */
347 int sfmt;
c906108c
SS
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
96baa820
JM
355 /* Index in IDESC table of read handler. */
356 int read_index;
c906108c
SS
357#endif
358
359#if WITH_PARALLEL_WRITE
96baa820 360 /* Index in IDESC table of writeback handler. */
c906108c
SS
361 int write_index;
362#endif
96baa820 363};
c906108c 364
96baa820
JM
365/* Entry in semantic function table.
366 This information is copied to the insn descriptor table at run-time. */
367
368struct 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;
c906108c
SS
374};
375
376/* Run-time computed instruction descriptor. */
377
378struct idesc {
96baa820 379#if WITH_SEM_SWITCH_FAST
c906108c 380#ifdef __GNUC__
96baa820 381 void *sem_fast_lab;
c906108c 382#else
96baa820 383 /* nothing needed, switch's on `num' member */
c906108c 384#endif
96baa820
JM
385#else
386 SEMANTIC_FN *sem_fast;
c906108c
SS
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
96baa820
JM
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;
c906108c
SS
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
96baa820
JM
410 /* Semantic format id. */
411 int sfmt;
412
c906108c
SS
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 */
This page took 0.053802 seconds and 4 git commands to generate.