OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [common/] [cgen-engine.h] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.