1 |
227 |
jeremybenn |
/* 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 |
|
|
|
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 */
|