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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [cgen/] [sim-cpu.scm] - Blame information for rev 6

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 6 jlechner
; CPU family related simulator generator, excluding decoding and model support.
2
; Copyright (C) 2000, 2001, 2009 Red Hat, Inc.
3
; This file is part of CGEN.
4
 
5
; - Add support to generate copies of semantic code and perform constant
6
;   folding based on selected mach.  This would collapse out untaken branches
7
;   of tests on (current-mach).
8
; Utilities of cgen-cpu.h.
9
 
10
; A "cpu family" here is a collection of variants of a particular architecture
11
 
12
"\
13
/* Maximum number of instructions that are fetched at a time.
14
   This is for LIW type instructions sets (e.g. m32r).  */
15
 
16
 
17
/* Maximum number of instructions that can be executed in parallel.  */
18
#define MAX_PARALLEL_INSNS ""\n\n";   (gen-enum-decl '@cpu@_virtual
19
;                 "@cpu@ virtual insns"
20
;                 "@ARCH@_INSN_" ; not @CPU@ to match CGEN_INSN_TYPE in opc.h
21
;                 '((x-invalid 0)
22
;                   (x-before -1) (x-after -2)
23
 
24
; Return a boolean indicating if hardware element HW needs storage allocated
25
; for it in the SIM_CPU struct.
26
; Subroutine of -gen-hardware-types to generate the struct containing
27
; hardware elements of one isa.
28
; If struct is empty, leave it out to simplify generated code.
29
""; Return C type declarations of all of the hardware elements.
30
; The name of the type is prepended with the cpu family name.
31
"/* CPU state information.  */\n""typedef struct {\n""  /* Hardware elements.  */\n""  struct {\n""  } hardware;\n""#define CPU_CGEN_HW(cpu) (& (cpu)->cpu_data.hardware)\n";"  /* CPU profiling state information.  */\n"
32
;"  struct {\n"
33
;(string-list-map (lambda (hw) (send hw 'gen-profile-decl))
34
;                   (find hw-profilable? (current-hw-list)))
35
 
36
;"#define CPU_CGEN_PROFILE(cpu) (& (cpu)->cpu_data.profile)\n"
37
"} @CPU@_CPU_DATA;\n\n"; If there are any virtual regs, output get/set macros for them.
38
 
39
"/* Cover fns for register access.  */\n""@cpu@""\n""/* These must be hand-written.  */\n""extern CPUREG_FETCH_FN @cpu@_fetch_register;\n""extern CPUREG_STORE_FN @cpu@_store_register;\n""\n"; Generate type of struct holding model state while executing.
40
"Generating model decls ...\n""typedef struct {\n""  int empty;\n"; ensure struct isn't empty so it compiles
41
"  "" "";\n""} MODEL_""_DATA;\n\n"; Utility of -gen-extract-macros to generate a macro to define the local
42
 
43
; for <iformat> IFMT.
44
"Processing format "" ...\n"""""; We don't need an extra blank line here as gen-extract-ifields adds one.
45
 
46
"Generating extraction macros ...\n""\
47
/* Macros to simplify extraction, reading and semantic code.
48
   These define and assign the local vars that contain the insn's fields.  */
49
\n"; Utility of -gen-parallel-exec-type to generate the definition of one
50
; structure in PAREXEC.
51
; SFMT is an <sformat> object.
52
"    struct { /* "" */\n""      int empty;\n"; ensure struct isn't empty so it compiles
53
"Processing operand "" of format "" ...\n""      "" "";\n""      "" ""_idx;\n""""      "" "";\n""    } "";\n"; Generate the definition of the structure that holds register values, etc.
54
; for use during parallel execution.  When instructions are executed parallelly
55
; either
56
; - their inputs are read before their outputs are written.  Thus we have to
57
; fetch the input values of several instructions before executing any of them.
58
; - or their outputs are queued here first and then written out after all insns
59
 
60
; The fetched/queued values are stored in an array of PAREXEC structs, one
61
; element per instruction.
62
 
63
 
64
struct parexec {
65
  union {\n""\
66
  } operands;
67
  /* For conditionally written operands, bitmask of which ones were.  */
68
  int written;
69
};\n\n"; Generate the TRACE_RECORD struct definition.
70
; This struct will hold all necessary data for doing tracing and profiling
71
; (e.g. register numbers).  The goal is to remove all tracing code from the
72
; semantic code.  Then the fast/full distinction needn't use conditionals to
73
; discard/include the tracing/profiling code.
74
"\
75
/* Collection of various things for the trace handler to use.  */
76
 
77
typedef struct trace_record {
78
  IADDR pc;
79
  /* FIXME:wip */
80
} TRACE_RECORD;
81
\n"; Utilities of cgen-cpu.c
82
; Get/set fns for every register.
83
"@cpu@""  return GET_"" (""""regno"");\n""  return CPU (""""[regno]"");\n""  SET_"" (""""regno, ""newval);\n""  CPU (""""[regno]"") = newval;\n"; Generate a function to record trace results in a trace record.
84
"\
85
/* Record trace results for INSN.  */
86
 
87
void
88
@cpu@_record_trace_results (SIM_CPU *current_cpu, CGEN_INSN *insn,
89
                            int *indices, TRACE_RECORD *tr)
90
{\n""}\n"; Utilities of cgen-read.c.
91
; Parallel-read support is not currently used by any port and this code
92
; has been left to bitrot.  Don't delete it just yet.
93
; Return C code to fetch and save all input operands to instructions with
94
; <sformat> SFMT.
95
; Utility of -gen-read-switch to generate a switch case for <sformat> SFMT.
96
"Processing read switch case for \"""\" ...\n""    CASE (read, READ_"") : ""/* "" */\n""    {\n""      ""      ""    }\n""    BREAK (read);\n\n"; Generate the guts of a C switch statement to read insn operands.
97
; The switch is based on instruction formats.
98
"Processing readers ...\n"; Utilities of cgen-write.c.
99
; This is the other way of implementing parallel execution support.
100
; Instead of fetching all the input operands first, write all the output
101
; operands and their addresses to holding variables, and then run a
102
; post-processing pass to update the cpu state.
103
;
104
; There are separate implementations for semantics as functions and semantics
105
; as one big switch.  For the function case we create a function that is a
106
; switch on each semantic format and loops writing each insn's results back.
107
; For the switch case we add cases to the switch to handle the write back,
108
; and it is up to the pbb compiler to include them in the generated "code".
109
; Return C code to fetch and save all output operands to instructions with
110
; <sformat> SFMT.
111
; Utility of gen-write-switch to generate a switch case for <sformat> SFMT.
112
; If INSN is non-#f, it is the <insn> object of the insn in which case
113
 
114
; current sem-switch support emits one handler per insn instead of per sfmt.
115
 
116
;(gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) "  " #f) - used by cgen-read.c
117
"    IADDR UNUSED pc = abuf->addr;\n""""    SEM_BRANCH_INIT\n"; no trailing `;' on purpose
118
"""    vpc = SEM_NEXT_VPC (sem_arg, pc, 0);\n""""\n""\n""  SEM_BRANCH_FINI (vpc);\n""""  }\n""  NEXT (vpc);\n""  break;\n""\n"; Generate the guts of a C switch statement to write insn operands.
119
; The switch is based on instruction formats.
120
; ??? This will generate cases for formats that don't need it.
121
; E.g. on the m32r all 32 bit insns can't be executed in parallel.
122
; It's easier to generate the code anyway so we do.
123
"Processing writers ...\n"; Utilities of cgen-semantics.c.
124
; Return name of semantic fn for INSN.
125
;(string-append "sem_" (gen-sym insn))
126
; Return semantic fn table entry for INSN.
127
"  { ""@PREFIX@_INSN_"", ""SEM_FN_NAME (@prefix@,"")"" },\n"; Return C code to define a table of all semantic fns and a function to
128
; add the info to the insn descriptor table.
129
"\
130
/* Table of all semantic fns.  */
131
 
132
static const struct sem_fn_desc sem_fns[] = {\n""\
133
 
134
};
135
 
136
/* Add the semantic fns to IDESC_TABLE.  */
137
 
138
void
139
SEM_FN_NAME (@prefix@,init_idesc_table) (SIM_CPU *current_cpu)
140
{
141
  IDESC *idesc_table = CPU_IDESC (current_cpu);
142
  const struct sem_fn_desc *sf;
143
  int mach_num = MACH_NUM (CPU_MACH (current_cpu));
144
 
145
  for (sf = &sem_fns[0]; sf->fn != 0; ++sf)
146
    {
147
      const CGEN_INSN *insn = idesc_table[sf->index].idata;
148
      int valid_p = (CGEN_INSN_VIRTUAL_P (insn)
149
                     || CGEN_INSN_MACH_HAS_P (insn, mach_num));
150
#if FAST_P
151
      if (valid_p)
152
        idesc_table[sf->index].sem_fast = sf->fn;
153
      else
154
        idesc_table[sf->index].sem_fast = SEM_FN_NAME (@prefix@,x_invalid);
155
 
156
      if (valid_p)
157
        idesc_table[sf->index].sem_full = sf->fn;
158
      else
159
 
160
#endif
161
    }
162
}
163
\n"; Return C code to perform the semantics of INSN.
164
"  ""\n"""; Indicate generating code for INSN.
165
; Use the compiled form if available.
166
; The case when they're not available is for virtual insns.
167
; Return definition of C function to perform INSN.
168
 
169
"Processing semantics for "": \"""\" ...\n""/* "": "" */\n\n""static SEM_PC\n""SEM_FN_NAME (@prefix@,"")"" (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec)\n"" (SIM_CPU *current_cpu, SEM_ARG sem_arg)\n""{\n""""  ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"; Unconditionally written operands are not recorded here.
170
 
171
; Note that the address recorded in the cpu state struct is not used.
172
; For faster engines that copy will be out of date.
173
"  IADDR UNUSED pc = abuf->addr;\n""  SEM_BRANCH_INIT\n"; no trailing `;' on purpose
174
"""  SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "");\n""\n""\n"; Only update what's been written if some are conditionally written.
175
; Otherwise we know they're all written so there's no point in
176
; keeping track.
177
"  abuf->written = written;\n""""  SEM_BRANCH_FINI (vpc);\n""""  return vpc;\n""""}\n\n"; Return definition of C function to perform INSN.
178
; This version handles the without-scache case.
179
; ??? TODO: multiword insns.
180
"Processing semantics for "": \"""\" ...\n""/* "": "" */\n\n""static SEM_STATUS\n""SEM_FN_NAME (@prefix@,"")"" (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec, CGEN_INSN_INT insn)\n"" (SIM_CPU *current_cpu, SEM_ARG sem_arg, CGEN_INSN_INT insn)\n""{\n""""  SEM_STATUS status = 0;\n"; ??? wip
181
 
182
"  int UNUSED written = 0;\n""  IADDR UNUSED pc = GET_H_PC ();\n""  SEM_BRANCH_INIT\n"; no trailing `;' on purpose
183
"""  SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "");\n""  ""  ""\n""\n"; Only update what's been written if some are conditionally written.
184
; Otherwise we know they're all written so there's no point in
185
 
186
"  abuf->written = written;\n"""; SEM_{,N}BRANCH_FINI are user-supplied macros.
187
"  SEM_BRANCH_FINI (vpc, ""  SEM_NBRANCH_FINI (vpc, "");\n""""  return status;\n""""}\n\n""Processing semantics ...\n"; Utility of -gen-sem-case to return the mask of operands always written
188
; to in <sformat> SFMT.
189
; ??? Not currently used.
190
; Utility of -gen-sem-case to return #t if any operand in <sformat> SFMT is
191
; conditionally written to.
192
; Generate a switch case to perform INSN.
193
"Processing ""parallel """"semantic switch case for \"""\" ...\n"; INSN_ is prepended here and not elsewhere to avoid name collisions
194
; with symbols like AND, etc.
195
"  CASE (sem, ""INSN_""PAR_"""") : ""/* "" */\n""{\n""  SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);\n""  ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"""; Unconditionally written operands are not recorded here.
196
"  int UNUSED written = 0;\n"; The address of this insn, needed by extraction and semantic code.
197
; Note that the address recorded in the cpu state struct is not used.
198
"  IADDR UNUSED pc = abuf->addr;\n""  SEM_BRANCH_INIT\n"; no trailing `;' on purpose
199
"""""  ""  ""\n""  vpc = SEM_NEXT_VPC (sem_arg, pc, "");\n""\n""\n"; Only update what's been written if some are conditionally written.
200
; Otherwise we know they're all written so there's no point in
201
; keeping track.
202
"  abuf->written = written;\n""""  SEM_BRANCH_FINI (vpc);\n""""""}\n""  NEXT (vpc);\n\n""Processing semantic switch ...\n"; Turn parallel execution support off.
203
; Generate the guts of a C switch statement to execute parallel instructions.
204
; This switch is included after the non-parallel instructions in the semantic
205
; switch.
206
;
207
; ??? We duplicate the writeback case for each insn, even though we only need
208
; one case per insn format.  The former keeps the code for each insn
209
; together and might improve cache usage.  On the other hand the latter
210
; reduces the amount of code, though it is believed that in this particular
211
; instance the win isn't big enough.
212
"Processing parallel insn semantic switch ...\n"; Turn parallel execution support on.
213
; Top level file generators.
214
; Generate cpu-<cpu>.h
215
 
216
; Tell the rtl->c translator we're not the simulator.
217
; ??? Minimizes changes in generated code until this is changed.
218
; RTL->C happens for field decoding.
219
"CPU family header for @cpu@.""\
220
#ifndef CPU_@CPU@_H
221
#define CPU_@CPU@_H
222
 
223
""""""#endif /* CPU_@CPU@_H */\n"; Generate defs-<isa>.h.
224
"Generating ""'s defs.h ...\n"; Tell the rtl->c translator we're not the simulator.
225
 
226
; RTL->C happens for field decoding.
227
"ISA definitions header for "".""\
228
#ifndef DEFS_@PREFIX@_H
229
#define DEFS_@PREFIX@_H
230
 
231
""#endif /* DEFS_@PREFIX@_H */\n"; Generate cpu-<cpu>.c
232
"Generating ""'s cpu.c ...\n"; Turn parallel execution support on if cpu needs it.
233
 
234
"Misc. support for CPU family @cpu@.""\
235
#define WANT_CPU @cpu@
236
#define WANT_CPU_@CPU@
237
 
238
#include \"sim-main.h\"
239
#include \"cgen-ops.h\"
240
 
241
"; Generate read.c
242
"Generating ""'s read.c ...\n"; Turn parallel execution support off.
243
; Tell the rtx->c translator we are the simulator.
244
 
245
#ifdef DEFINE_LABELS
246
 
247
  /* The labels have the case they have because the enum of insn types
248
     is all uppercase and in the non-stdc case the fmt symbol is built
249
     into the enum name.  */
250
 
251
  static struct {
252
    int index;
253
    void *label;
254
  } labels[] = {\n""    { ""@PREFIX@_INSN_"", && case_read_READ_"" },\n""    { 0, 0 }
255
 
256
  int i;
257
 
258
  for (i = 0; labels[i].label != 0; ++i)
259
    CPU_IDESC (current_cpu) [labels[i].index].read = labels[i].label;
260
 
261
#undef DEFINE_LABELS
262
#endif /* DEFINE_LABELS */
263
 
264
#ifdef DEFINE_SWITCH
265
 
266
{\n""\
267
 
268
  ARGBUF *abuf = SEM_ARGBUF (sem_arg);
269
 
270
  SWITCH (read, sem_arg->read)\n""\
271
  SWITCH (read, decode->read)\n""\
272
    {
273
 
274
""\
275
    }
276
  ENDSWITCH (read) /* End of read switch.  */
277
}
278
 
279
#undef DEFINE_SWITCH
280
#endif /* DEFINE_SWITCH */
281
"; Generate write.c
282
"Generating ""'s write.c ...\n"; Turn parallel execution support off.
283
; Tell the rtx->c translator we are the simulator.
284
"Simulator instruction operand writer for "".""\
285
/* Write cached results of 1 or more insns executed in parallel.  */
286
 
287
void
288
@cpu@_parallel_write (SIM_CPU *cpu, SCACHE *sbufs, PAREXEC *pbufs, int ninsns)
289
{\n""\
290
  SEM_ARG sem_arg = sc;
291
  ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n""""\
292
 
293
  do
294
    {
295
      ARGBUF *abuf = SEM_ARGBUF (sbufs);
296
 
297
      switch (abuf->idesc->write)
298
        {
299
\n";(/indent-add 8)
300
;(/indent-add -8)
301
"\
302
        }
303
    }
304
  while (--ninsns > 0);
305
}
306
 
307
; Each instruction is implemented in its own function.
308
 
309
; Tell the rtx->c translator we are the simulator.
310
"Simulator instruction semantics for @cpu@.""\
311
#define WANT_CPU @cpu@
312
#define WANT_CPU_@CPU@
313
 
314
#include \"sim-main.h\"
315
#include \"cgen-mem.h\"
316
#include \"cgen-ops.h\"
317
 
318
#undef GET_ATTR
319
""GET_ATTR(cpu, num, attr) \
320
CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_""attr)""
321
 
322
   one with full feature support and one without that runs fast(er).
323
   FAST_P, when desired, is defined on the command line, -DFAST_P=1.  */
324
#if FAST_P
325
 
326
#undef TRACE_RESULT
327
#define TRACE_RESULT(cpu, abuf, name, type, val)
328
 
329
#define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
330
#endif
331
\n"; Put the table at the end so we don't have to declare all the sem fns.
332
; Generate sem-switch.c.
333
 
334
; This file consists of just the switch().  It is included by mainloop.c.
335
 
336
; It is later turned on/off when generating the actual semantic code.
337
; Tell the rtx->c translator we are the simulator.
338
"Simulator instruction semantics for @cpu@.""\
339
#ifdef DEFINE_LABELS
340
 
341
  /* The labels have the case they have because the enum of insn types
342
     is all uppercase and in the non-stdc case the insn symbol is built
343
     into the enum name.  */
344
 
345
  static struct {
346
    int index;
347
    void *label;
348
  } labels[] = {\n""    { ""@PREFIX@_INSN_"", && case_sem_INSN_"" },\n""    { ""@CPU@_INSN_PAR_"", && case_sem_INSN_PAR_"" },\n""    { ""@CPU@_INSN_WRITE_"", && case_sem_INSN_WRITE_"" },\n""""    { 0, 0 }
349
  };
350
  int i;
351
 
352
  for (i = 0; labels[i].label != 0; ++i)
353
 
354
#if FAST_P
355
      CPU_IDESC (current_cpu) [labels[i].index].sem_fast_lab = labels[i].label;
356
 
357
      CPU_IDESC (current_cpu) [labels[i].index].sem_full_lab = labels[i].label;
358
#endif
359
    }
360
 
361
 
362
#endif /* DEFINE_LABELS */
363
 
364
#ifdef DEFINE_SWITCH
365
 
366
/* If hyper-fast [well not unnecessarily slow] execution is selected, turn
367
   off frills like tracing and profiling.  */
368
/* FIXME: A better way would be to have TRACE_RESULT check for something
369
   that can cause it to be optimized out.  Another way would be to emit
370
   special handlers into the instruction \"stream\".  */
371
 
372
#if FAST_P
373
#undef TRACE_RESULT
374
 
375
#endif
376
 
377
 
378
""GET_ATTR(cpu, num, attr) \
379
CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_""attr)""
380
{
381
 
382
 
383
 
384
/* Branch to next handler without going around main loop.  */
385
#define NEXT(vpc) goto * SEM_ARGBUF (vpc) -> semantic.sem_case
386
SWITCH (sem, SEM_ARGBUF (vpc) -> semantic.sem_case)
387
 
388
#else /* ! WITH_SCACHE_PBB */
389
 
390
#define NEXT(vpc) BREAK (sem)
391
#ifdef __GNUC__
392
#if FAST_P
393
  SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_fast_lab)
394
#else
395
  SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_full_lab)
396
#endif
397
#else
398
  SWITCH (sem, SEM_ARGBUF (sc) -> idesc->num)
399
#endif
400
 
401
#endif /* ! WITH_SCACHE_PBB */
402
 
403
    {
404
 
405
""""
406
    }
407
  ENDSWITCH (sem) /* End of semantic switch.  */
408
 
409
  /* At this point `vpc' contains the next insn to execute.  */
410
}
411
 
412
#undef DEFINE_SWITCH
413
#endif /* DEFINE_SWITCH */
414
"; Generate mainloop.in.
415
; ??? Not currently used.
416
"Generating mainloop.in ...\n""cat <<EOF >/dev/null\n""Simulator main loop for @arch@.""EOF\n""\
417
 
418
# Syntax:
419
# /bin/sh mainloop.in init|support|{full,fast}-{extract,exec}-{scache,nocache}
420
 
421
# ??? There's lots of conditional compilation here.
422
# After a few more ports are done, revisit.
423
 
424
case \"x$1\" in
425
 
426
xsupport)
427
 
428
cat <<EOF
429
/*xsupport*/
430
EOF
431
 
432
;;
433
 
434
xinit)
435
 
436
cat <<EOF
437
/*xinit*/
438
EOF
439
 
440
;;
441
 
442
xfull-extract-* | xfast-extract-*)
443
 
444
 
445
{
446
""}
447
EOF
448
 
449
;;
450
 
451
xfull-exec-* | xfast-exec-*)
452
 
453
cat <<EOF
454
{
455
""}
456
EOF
457
 
458
;;
459
 
460
*)
461
 
462
  exit 1
463
  ;;
464
 
465
esac
466
 

powered by: WebSVN 2.1.0

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