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 |
|
|
|