OSDN Git Service

Use datarootdir for locales.
[pf3gnuchains/pf3gnuchains4x.git] / cgen / sim-decode.scm
1 ; Decoder generation.
2 ; Copyright (C) 2000, 2001, 2009, 2010 Red Hat, Inc.
3 ; This file is part of CGEN.
4
5 ; Names of various global vars.
6
7 ; Name of insn descriptor table var.
8 (define IDESC-TABLE-VAR "@prefix@_insn_data")
9
10 ; Return decode entries for each insn.
11 ; ??? At one point we generated one variable per instruction rather than one
12 ; big array.  It doesn't matter too much (yet).  Generating one big array is
13 ; simpler.
14
15 (define (/gen-decode-insn-globals insn-list)
16   ; Print the higher detailed stuff at higher verbosity.
17   (logit 2 "Processing decode insn globals ...\n")
18
19   (string-write
20
21    (if (and (with-parallel?) (not (with-parallel-only?)))
22        "\
23 /* Insn can't be executed in parallel.
24    Or is that \"do NOt Pass to Air defense Radar\"? :-) */
25 #define NOPAR (-1)
26 \n"
27        "")
28
29    "\
30 /* The instruction descriptor array.
31    This is computed at runtime.  Space for it is not malloc'd to save a
32    teensy bit of cpu in the decoder.  Moving it to malloc space is trivial
33    but won't be done until necessary (we don't currently support the runtime
34    addition of instructions nor an SMP machine with different cpus).  */
35 static IDESC " IDESC-TABLE-VAR "[@PREFIX@_INSN__MAX];
36
37 /* Commas between elements are contained in the macros.
38    Some of these are conditionally compiled out.  */
39
40 static const struct insn_sem @prefix@_insn_sem[] =
41 {\n"
42
43    (string-list-map
44     (lambda (insn)
45       (let ((name (gen-sym insn))
46             (pbb? (obj-has-attr? insn 'PBB))
47             (virtual? (insn-virtual? insn)))
48         (string-list
49          "  { "
50          (if virtual?
51              (string-append "VIRTUAL_INSN_" (string-upcase name) ", ")
52              (string-append "@ARCH@_INSN_" (string-upcase name) ", "))
53          (string-append "@PREFIX@_INSN_" (string-upcase name) ", ")
54          "@PREFIX@_" (/gen-fmt-enum (insn-sfmt insn))
55          (if (and (with-parallel?) (not (with-parallel-only?)))
56              (string-list
57               (if (insn-parallel? insn)
58                   (string-append ", @PREFIX@_INSN_PAR_"
59                                  (string-upcase name)
60                                  ", "
61                                  (if (with-parallel-read?)
62                                      "@PREFIX@_INSN_READ_"
63                                      "@PREFIX@_INSN_WRITE_")
64                                  (string-upcase name))
65                   ", NOPAR, NOPAR "))
66              "")
67          " },\n")))
68     insn-list)
69
70    "\
71 };
72
73 static const struct insn_sem @prefix@_insn_sem_invalid =
74 {
75   VIRTUAL_INSN_X_INVALID, @PREFIX@_INSN_X_INVALID, @PREFIX@_SFMT_EMPTY"
76    (if (and (with-parallel?) (not (with-parallel-only?)))
77        ", NOPAR, NOPAR"
78        "")
79    "
80 };
81 \n"
82    )
83 )
84
85 ; Return enum name of format FMT.
86
87 (define (/gen-fmt-enum fmt)
88   (string-upcase (gen-sym fmt))
89 )
90 \f
91 ; Generate decls for the insn descriptor table type IDESC.
92
93 (define (/gen-idesc-decls)
94   (string-append "\
95 extern const IDESC *@prefix@_decode (SIM_CPU *, IADDR,
96                                   CGEN_INSN_WORD,"
97   (if (adata-integral-insn? CURRENT-ARCH)
98       " CGEN_INSN_WORD,\n"
99       "\n")
100   "\
101                                   ARGBUF *);
102 extern void @prefix@_init_idesc_table (SIM_CPU *);
103 extern void @prefix@_sem_init_idesc_table (SIM_CPU *);
104 extern void @prefix@_semf_init_idesc_table (SIM_CPU *);
105 \n")
106 )
107
108 ; Return definition of C function to initialize the IDESC table.
109 ; @prefix@_init_idesc_table is defined here as it depends on with-parallel?
110 ; and thus can't be defined in sim/common.
111
112 (define (/gen-idesc-init-fn)
113   (string-append "\
114 /* Initialize an IDESC from the compile-time computable parts.  */
115
116 static INLINE void
117 init_idesc (SIM_CPU *cpu, IDESC *id, const struct insn_sem *t)
118 {
119   const CGEN_INSN *insn_table = CGEN_CPU_INSN_TABLE (CPU_CPU_DESC (cpu))->init_entries;
120
121   id->num = t->index;
122   id->sfmt = t->sfmt;
123   if ((int) t->type <= 0)
124     id->idata = & cgen_virtual_insn_table[- (int) t->type];
125   else
126     id->idata = & insn_table[t->type];
127   id->attrs = CGEN_INSN_ATTRS (id->idata);
128   /* Oh my god, a magic number.  */
129   id->length = CGEN_INSN_BITSIZE (id->idata) / 8;
130
131 #if WITH_PROFILE_MODEL_P
132   id->timing = & MODEL_TIMING (CPU_MODEL (cpu)) [t->index];
133   {
134     SIM_DESC sd = CPU_STATE (cpu);
135     SIM_ASSERT (t->index == id->timing->num);
136   }
137 #endif
138
139   /* Semantic pointers are initialized elsewhere.  */
140 }
141
142 /* Initialize the instruction descriptor table.  */
143
144 void
145 @prefix@_init_idesc_table (SIM_CPU *cpu)
146 {
147   IDESC *id,*tabend;
148   const struct insn_sem *t,*tend;
149   int tabsize = @PREFIX@_INSN__MAX;
150   IDESC *table = " IDESC-TABLE-VAR ";
151
152   memset (table, 0, tabsize * sizeof (IDESC));
153
154   /* First set all entries to the `invalid insn'.  */
155   t = & @prefix@_insn_sem_invalid;
156   for (id = table, tabend = table + tabsize; id < tabend; ++id)
157     init_idesc (cpu, id, t);
158
159   /* Now fill in the values for the chosen cpu.  */
160   for (t = @prefix@_insn_sem, tend = t + sizeof (@prefix@_insn_sem) / sizeof (*t);
161        t != tend; ++t)
162     {
163       init_idesc (cpu, & table[t->index], t);\n"
164
165    (if (and (with-parallel?) (not (with-parallel-only?)))
166        "\
167       if (t->par_index != NOPAR)
168         {
169           init_idesc (cpu, &table[t->par_index], t);
170           table[t->index].par_idesc = &table[t->par_index];
171         }\n"
172        "")
173
174    (if (and (with-parallel-write?) (not (with-parallel-only?)))
175        "\
176       if (t->par_index != NOPAR)
177         {
178           init_idesc (cpu, &table[t->write_index], t);
179           table[t->par_index].par_idesc = &table[t->write_index];
180         }\n"
181        "")
182
183    "\
184     }
185
186   /* Link the IDESC table into the cpu.  */
187   CPU_IDESC (cpu) = table;
188 }
189
190 ")
191 )
192 \f
193 ; Instruction field extraction support.
194 ; Two implementations are provided, one for !with-scache and one for
195 ; with-scache.
196 ;
197 ; Extracting ifields is a three phase process.  First the ifields are
198 ; extracted and stored in local variables.  Then any ifields requiring
199 ; additional processing for operands are handled.  Then in the with-scache
200 ; case the results are stored in a struct for later retrieval by the semantic
201 ; code.
202 ;
203 ; The !with-scache case does this processing in the semantic function,
204 ; except it doesn't need the last step (it doesn't need to store the results
205 ; in a struct for later use).
206 ;
207 ; The with-scache case extracts the ifields in the decode function.
208 ; Furthermore, we use <sformat-argbuf> to reduce the quantity of structures
209 ; created (this helps semantic-fragment pbb engines).
210
211 ; Return C code to record <ifield> F for the semantic handler
212 ; in a local variable rather than an ARGBUF struct.
213
214 (define (/gen-record-argbuf-ifld f sfmt)
215   (string-append "  " (gen-ifld-argbuf-ref f)
216                  " = " (gen-extracted-ifld-value f) ";\n")
217 )
218
219 ; Return three of arguments to TRACE:
220 ; string argument to fprintf, character indicating type of third arg, value.
221 ; The type is one of: x.
222
223 (define (/gen-trace-argbuf-ifld f sfmt)
224   (string-append
225    ; FIXME: Add method to return fprintf format string.
226    ", \"" (gen-sym f) " 0x%x\""
227    ", 'x'"
228    ", " (gen-extracted-ifld-value f))
229 )
230 \f
231 ; Instruction field extraction support cont'd.
232 ; Hardware support.
233
234 ; gen-extract method.
235 ; For the default case we use the ifield as is, which is output elsewhere.
236
237 (method-make!
238  <hardware-base> 'gen-extract
239  (lambda (self op sfmt local?)
240    "")
241 )
242
243 ; gen-trace-extract method.
244 ; Return appropriate arguments for TRACE_EXTRACT.
245
246 (method-make!
247  <hardware-base> 'gen-trace-extract
248  (lambda (self op sfmt)
249    "")
250 )
251
252 ; Extract the necessary fields into ARGBUF.
253
254 (method-make!
255  <hw-register> 'gen-extract
256  (lambda (self op sfmt local?)
257    (if (hw-cache-addr? self)
258        (string-append "  "
259                       (if local?
260                           (gen-hw-index-argbuf-name (op:index op))
261                           (gen-hw-index-argbuf-ref (op:index op)))
262                       " = & "
263                       (gen-cpu-ref (gen-sym (op:type op)))
264                       (gen-array-ref (gen-extracted-ifld-value (op-ifield op)))
265                       ";\n")
266        ""))
267 )
268
269 ; Return appropriate arguments for TRACE_EXTRACT.
270
271 (method-make!
272  <hw-register> 'gen-trace-extract
273  (lambda (self op sfmt)
274    (if (hw-cache-addr? self)
275        (string-append
276         ; FIXME: Add method to return fprintf format string.
277         ", \"" (gen-sym op) " 0x%x\""
278         ", 'x'"
279         ", " (gen-extracted-ifld-value (op-ifield op)))
280        ""))
281 )
282
283 ; Extract the necessary fields into ARGBUF.
284
285 (method-make!
286  <hw-address> 'gen-extract
287  (lambda (self op sfmt local?)
288    (string-append "  "
289                   (if local?
290                       (gen-hw-index-argbuf-name (op:index op))
291                       (gen-hw-index-argbuf-ref (op:index op)))
292                   " = "
293                   (gen-extracted-ifld-value (op-ifield op))
294                   ";\n"))
295 )
296
297 ; Return appropriate arguments for TRACE_EXTRACT.
298
299 (method-make!
300  <hw-address> 'gen-trace-extract
301  (lambda (self op sfmt)
302    (string-append
303     ; FIXME: Add method to return fprintf format string.
304     ", \"" (gen-sym op) " 0x%x\""
305     ", 'x'"
306     ", " (gen-extracted-ifld-value (op-ifield op))))
307 )
308 \f
309 ; Instruction field extraction support cont'd.
310 ; Operand support.
311
312 ; Return C code to record the field for the semantic handler.
313 ; In the case of a register, this is usually the address of the register's
314 ; value (if CACHE-ADDR).
315 ; LOCAL? indicates whether to record the value in a local variable or in
316 ; the ARGBUF struct.
317 ; ??? Later allow target to provide an `extract' expression.
318
319 (define (/gen-op-extract op sfmt local?)
320   (send (op:type op) 'gen-extract op sfmt local?)
321 )
322
323 ; Return three of arguments to TRACE_EXTRACT:
324 ; string argument to fprintf, character indicating type of third arg, value.
325 ; The type is one of: x.
326
327 (define (/gen-op-trace-extract op sfmt)
328   (send (op:type op) 'gen-trace-extract op sfmt)
329 )
330
331 ; Return C code to define local vars to hold processed ifield data for
332 ; <sformat> SFMT.
333 ; This is used when !with-scache.
334 ; Definitions of the extracted ifields is handled elsewhere.
335
336 (define (gen-sfmt-op-argbuf-defns sfmt)
337   (let ((operands (sfmt-extracted-operands sfmt)))
338     (string-list-map (lambda (op)
339                        (let ((var-spec (sfmt-op-sbuf-elm op sfmt)))
340                          (if var-spec
341                              (string-append "  "
342                                             (cadr var-spec)
343                                             " "
344                                             (car var-spec)
345                                             ";\n")
346                              "")))
347                      operands))
348 )
349
350 ; Return C code to assign values to the local vars that hold processed ifield
351 ; data for <sformat> SFMT.
352 ; This is used when !with-scache.
353 ; Assignment of the extracted ifields is handled elsewhere.
354
355 (define (gen-sfmt-op-argbuf-assigns sfmt)
356   (let ((operands (sfmt-extracted-operands sfmt)))
357     (string-list-map (lambda (op)
358                        (/gen-op-extract op sfmt #t))
359                      operands))
360 )
361 \f
362 ; Instruction field extraction support cont'd.
363 ; Emit extraction section of decode function.
364
365 ; Return C code to record insn field data for <sformat> SFMT.
366 ; This is used when with-scache.
367
368 (define (/gen-record-args sfmt)
369   (let ((operands (sfmt-extracted-operands sfmt))
370         (iflds (sfmt-needed-iflds sfmt)))
371     (string-list
372      "  /* Record the fields for the semantic handler.  */\n"
373      (string-list-map (lambda (f) (/gen-record-argbuf-ifld f sfmt))
374                       iflds)
375      (string-list-map (lambda (op) (/gen-op-extract op sfmt #f))
376                       operands)
377      "  TRACE_EXTRACT (current_cpu, abuf, (current_cpu, pc, "
378      "\"" (gen-sym sfmt) "\""
379      (string-list-map (lambda (f) (/gen-trace-argbuf-ifld f sfmt))
380                       iflds)
381      (string-list-map (lambda (op) (/gen-op-trace-extract op sfmt))
382                       operands)
383      ", (char *) 0));\n"
384      ))
385 )
386
387 ; Return C code to record insn field data for profiling.
388 ; Also recorded are operands not mentioned in the fields but mentioned
389 ; in the semantic code.
390 ;
391 ; FIXME: Register usage may need to be tracked as an array of longs.
392 ; If there are more than 32 regs, we can't know which until build time.
393 ; ??? For now we only handle reg sets of 32 or less.
394 ;
395 ; ??? The other way to obtain register numbers is to defer computing them
396 ; until they're actually needed.  It will speed up execution when not doing
397 ; profiling, though the speed up is only for the extraction phase.
398 ; On the other hand the current way has one memory reference per register
399 ; number in the profiling routines.  For RISC this can be a lose, though for
400 ; more complicated instruction sets it could be a win as all the computation
401 ; is kept to the extraction phase.  If someone wants to put forth some real
402 ; data, this might then be changed (or at least noted).
403
404 (define (/gen-record-profile-args sfmt)
405   (let ((in-ops (find op-profilable? (sfmt-in-ops sfmt)))
406         (out-ops (find op-profilable? (sfmt-out-ops sfmt)))
407         )
408     (if (and (null? in-ops) (null? out-ops))
409         ""
410         (string-list
411          "#if WITH_PROFILE_MODEL_P\n"
412          "  /* Record the fields for profiling.  */\n"
413          "  if (PROFILE_MODEL_P (current_cpu))\n"
414          "    {\n"
415          (string-list-map (lambda (op) (op:record-profile op sfmt #f))
416                           in-ops)
417          (string-list-map (lambda (op) (op:record-profile op sfmt #t))
418                           out-ops)
419          "    }\n"
420          "#endif\n"
421          )))
422 )
423
424 ; Return C code that extracts the fields of <sformat> SFMT.
425 ;
426 ; Extraction is based on formats to reduce the amount of code generated.
427 ; However, we also need to emit code which records the hardware elements used
428 ; by the semantic code.  This is currently done by recording this information
429 ; with the format.
430
431 (define (/gen-extract-case sfmt)
432   (logit 2 "Processing extractor for \"" (sfmt-key sfmt) "\" ...\n")
433   (string-list
434    " extract_" (gen-sym sfmt) ":\n"
435    "  {\n"
436    "    const IDESC *idesc = &" IDESC-TABLE-VAR "[itype];\n"
437    (if (> (length (sfmt-iflds sfmt)) 0)
438        (string-append
439         "    CGEN_INSN_WORD insn = "
440         (if (adata-integral-insn? CURRENT-ARCH)
441             "entire_insn;\n"
442             "base_insn;\n"))
443        "")
444    (gen-define-field-macro sfmt)
445    (gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) "    " #f)
446    "\n"
447    (gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) "    " #f)
448    "\n"
449    (/gen-record-args sfmt)
450    "\n"
451    (/gen-record-profile-args sfmt)
452    (gen-undef-field-macro sfmt)
453    "    return idesc;\n"
454    "  }\n\n"
455    )
456 )
457
458 ; For each format, return its extraction function.
459
460 (define (/gen-all-extractors)
461   (logit 2 "Processing extractors ...\n")
462   (string-list-map /gen-extract-case (current-sfmt-list))
463 )
464 \f
465 ; Generate top level decoder.
466 ; INITIAL-BITNUMS is a target supplied list of bit numbers to use to
467 ; build the first decode table.  If nil, we compute 8 bits of it (FIXME)
468 ; ourselves.
469 ; LSB0? is non-#f if bit number 0 is the least significant bit.
470
471 (define (/gen-decode-fn insn-list initial-bitnums lsb0?)
472
473   ; Compute the initial DECODE-BITSIZE as the minimum of all insn lengths.
474   ; The caller of @prefix@_decode must fetch and pass exactly this number of bits
475   ; of the instruction.
476   ; ??? Make this a parameter later but only if necessary.
477
478   (let ((decode-bitsize (apply min (map insn-base-mask-length insn-list))))
479
480     ; Compute INITIAL-BITNUMS if not supplied.
481     ; 0 is passed for the start bit (it is independent of lsb0?)
482     (if (null? initial-bitnums)
483         (set! initial-bitnums (decode-get-best-bits insn-list nil
484                                                     0 ; startbit
485                                                     8 ; max
486                                                     decode-bitsize
487                                                     lsb0?)))
488
489     ; All set.  gen-decoder does the hard part, we just print out the result. 
490     (let ((decode-code (gen-decoder insn-list initial-bitnums
491                                     decode-bitsize
492                                     "    " lsb0?
493                                     (current-insn-lookup 'x-invalid #f)
494                                     #f)))
495
496       (string-write
497        "\
498 /* Given an instruction, return a pointer to its IDESC entry.  */
499
500 const IDESC *
501 @prefix@_decode (SIM_CPU *current_cpu, IADDR pc,
502               CGEN_INSN_WORD base_insn,"
503        (if (adata-integral-insn? CURRENT-ARCH)
504            " CGEN_INSN_WORD entire_insn,\n"
505            "\n")
506        "\
507               ARGBUF *abuf)
508 {
509   /* Result of decoder.  */
510   @PREFIX@_INSN_TYPE itype;
511
512   {
513     CGEN_INSN_WORD insn = base_insn;
514 \n"
515
516        decode-code
517
518        "\
519   }
520 \n"
521
522        (if (with-scache?)
523            (string-list "\
524   /* The instruction has been decoded, now extract the fields.  */\n\n"
525             /gen-all-extractors)
526            ; Without the scache, extraction is defered until the semantic code.
527            (string-list "\
528   /* Extraction is defered until the semantic code.  */
529
530  done:
531   return &" IDESC-TABLE-VAR "[itype];\n"))
532
533        "\
534 }\n"
535        )))
536 )
537 \f
538 ; Entry point.  Generate decode.h.
539
540 (define (cgen-decode.h)
541   (logit 1 "Generating " (gen-cpu-name) "'s decode.h ...\n")
542
543   (sim-analyze-insns!)
544
545   ; Turn parallel execution support on if cpu needs it.
546   (set-with-parallel?! (state-parallel-exec?))
547
548   (string-write
549    (gen-c-copyright "Decode header for @prefix@."
550                   CURRENT-COPYRIGHT CURRENT-PACKAGE)
551    "\
552 #ifndef @PREFIX@_DECODE_H
553 #define @PREFIX@_DECODE_H
554
555 "
556    /gen-idesc-decls
557    (lambda () (gen-cpu-insn-enum-decl (current-cpu)
558                                       (non-multi-insns (non-alias-insns (current-insn-list)))))
559    (lambda () (gen-sfmt-enum-decl (current-sfmt-list)))
560    gen-model-fn-decls
561    "#endif /* @PREFIX@_DECODE_H */\n"
562    )
563 )
564 \f
565 ; Entry point.  Generate decode.c.
566
567 (define (cgen-decode.c)
568   (logit 1 "Generating " (gen-cpu-name) "'s decode.c ...\n")
569
570   (sim-analyze-insns!)
571
572   ; Turn parallel execution support on if cpu needs it.
573   (set-with-parallel?! (state-parallel-exec?))
574
575   ; Tell the rtx->c translator we are the simulator.
576   (rtl-c-config! #:rtl-cover-fns? #t)
577
578   (string-write
579    (gen-c-copyright "Simulator instruction decoder for @prefix@."
580                   CURRENT-COPYRIGHT CURRENT-PACKAGE)
581    "\
582 #define WANT_CPU @cpu@
583 #define WANT_CPU_@CPU@
584
585 #include \"sim-main.h\"
586 #include \"sim-assert.h\"\n\n"
587
588    (lambda () (/gen-decode-insn-globals (non-multi-insns (non-alias-insns (current-insn-list)))))
589    /gen-idesc-init-fn
590    (lambda () (/gen-decode-fn (real-insns (current-insn-list))
591                               (state-decode-assist)
592                               (current-arch-insn-lsb0?)))
593    )
594 )