2 ; Copyright (C) 2000, 2002, 2003, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
5 ; Return decode entries for each insn.
6 ; ??? At one point we generated one variable per instruction rather than one
7 ; big array. It doesn't matter too much (yet). Generating one big array is
10 (define (/gen-decode-insn-globals insn-list)
11 ; Print the higher detailed stuff at higher verbosity.
12 (logit 2 "Processing decode insn globals ...\n")
14 (let* ((all-attrs (current-insn-attr-list))
15 (last-insn (string-upcase (gen-c-symbol (caar (list-take -1
16 (gen-obj-list-enums (non-multi-insns (current-insn-list)))))))))
20 // The instruction descriptor array.
25 // Have label pointers been initialized?
26 // XXX: Note that this is also needed by when semantics are implemented as
27 // functions to handle machine variants.
28 bool @prefix@_idesc::idesc_table_initialized_p = false;\n\n"
32 @prefix@_idesc @prefix@_idesc::idesc_table[@PREFIX@_INSN_" last-insn " + 1] =
37 (let ((name (gen-sym insn))
38 (sfmt (insn-sfmt insn))
39 (pbb? (obj-has-attr? insn 'PBB))
40 (virtual? (obj-has-attr? insn 'VIRTUAL)))
49 (string-append (/gen-sem-fn-name insn) ", "))
51 "\"" (string-upcase name) "\", "
52 (gen-cpu-insn-enum (current-cpu) insn)
54 (gen-obj-attr-sid-defn 'insn insn all-attrs)
62 ; Return a function that lookups up virtual insns.
64 (define (/gen-virtual-insn-finder)
67 // Given a canonical virtual insn id, return the target specific one.
70 @prefix@_idesc::lookup_virtual (virtual_insn_type vit)
74 case VIRTUAL_INSN_INVALID: return @PREFIX@_INSN_X_INVALID;
79 case VIRTUAL_INSN_BEGIN: return @PREFIX@_INSN_X_BEGIN;
80 case VIRTUAL_INSN_CHAIN: return @PREFIX@_INSN_X_CHAIN;
81 case VIRTUAL_INSN_CTI_CHAIN: return @PREFIX@_INSN_X_CTI_CHAIN;
82 case VIRTUAL_INSN_BEFORE: return @PREFIX@_INSN_X_BEFORE;
83 case VIRTUAL_INSN_AFTER: return @PREFIX@_INSN_X_AFTER;
87 (state-conditional-exec?))
89 case VIRTUAL_INSN_COND: return @PREFIX@_INSN_X_COND;
91 ; Unused, but may still be requested. Just return X_INVALID.
93 case VIRTUAL_INSN_COND: return @PREFIX@_INSN_X_INVALID;
102 ; Return enum name of format FMT.
104 (define (/gen-fmt-enum fmt)
105 (string-upcase (gen-sym fmt))
108 ; Return names of semantic fns for INSN.
109 ; ??? Make global, call from gen-semantic-fn, blah blah blah.
111 (define (/gen-sem-fn-name insn)
112 (string-append "@prefix@_sem_" (gen-sym insn))
115 ; Return decls of each semantic fn.
117 (define (/gen-sem-fn-decls)
119 "// Decls of each semantic fn.\n\n"
120 "using @cpu@::@prefix@_sem_fn;\n"
121 (string-list-map (lambda (insn)
122 (string-list "extern @prefix@_sem_fn "
123 (/gen-sem-fn-name insn)
125 (scache-engine-insns))
133 ; idesc, argbuf, and scache types
135 ; Generate decls for the insn descriptor table type IDESC.
137 (define (/gen-idesc-decls)
142 struct @prefix@_scache;
145 "typedef void (@prefix@_sem_fn) (@cpu@_cpu* cpu, @prefix@_scache* sem, int tick, @prefix@::write_stacks &buf);"
146 "typedef sem_status (@prefix@_sem_fn) (@cpu@_cpu* cpu, @prefix@_scache* sem);")
150 // Instruction descriptor.
152 struct @prefix@_idesc {
157 // computed-goto label pointer (pbb engine)
158 // FIXME: frag case to be redone (should instead point to usage table).
159 cgoto_label cgoto;\n\n"
164 // scache engine executor for this insn
165 @prefix@_sem_fn* execute;\n\n"
169 const char* insn_name;
170 enum @prefix@_insn_type sem_index;
171 @arch@_insn_attr attrs;
173 // idesc table: indexed by sem_index
174 static @prefix@_idesc idesc_table[];
180 // semantic label pointers filled_in?
181 static bool idesc_table_initialized_p;\n"
186 static @prefix@_insn_type lookup_virtual (virtual_insn_type vit);
192 ; Utility of /gen-argbuf-fields-union to generate the definition for
193 ; <sformat-abuf> SBUF.
195 (define (/gen-argbuf-elm sbuf)
196 (logit 2 "Processing sbuf format " (obj:name sbuf) " ...\n")
198 " struct { /* " (obj:comment sbuf) " */\n"
199 (let ((elms (sbuf-elms sbuf)))
202 (string-list-map (lambda (elm)
209 " } " (gen-sym sbuf) ";\n")
212 ; Utility of /gen-scache-decls to generate the union of extracted ifields.
214 (define (/gen-argbuf-fields-union)
217 // Instruction argument buffer.
219 union @prefix@_sem_fields {\n"
220 (string-list-map /gen-argbuf-elm (current-sbuf-list))
222 // This one is for chain/cti-chain virtual insns.
224 // Number of insns in pbb.
226 // This is used by chain insns and by untaken conditional branches.
227 @prefix@_scache* next;
228 @prefix@_scache* branch_target;
230 // This one is for `before' virtual insns.
232 // The cache entry of the real insn.
233 @prefix@_scache* insn;
239 (define (/gen-scache-decls)
241 (/gen-argbuf-fields-union)
243 // Simulator instruction cache.
245 struct @prefix@_scache {
253 (if (state-conditional-exec?)
261 // PC of this instruction.
265 @prefix@_idesc* idesc;
268 @prefix@_sem_fields fields;
270 " (if (with-any-profile?)
273 // Only used if profiling or parallel execution support enabled during
275 unsigned long long written;
279 // decode given instruction
280 void decode (@cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn);
286 ; Instruction field extraction support.
287 ; Two implementations are provided, one for !with-scache and one for
290 ; Extracting ifields is a three phase process. First the ifields are
291 ; extracted and stored in local variables. Then any ifields requiring
292 ; additional processing for operands are handled. Then in the with-scache
293 ; case the results are stored in a struct for later retrieval by the semantic
296 ; The !with-scache case does this processing in the semantic function,
297 ; except it doesn't need the last step (it doesn't need to store the results
298 ; in a struct for later use).
300 ; The with-scache case extracts the ifields in the decode function.
301 ; Furthermore, we use <sformat-argbuf> to reduce the quantity of structures
302 ; created (this helps semantic-fragment pbb engines).
304 ; Return C code to record <ifield> F for the semantic handler
305 ; in a local variable rather than an ARGBUF struct.
307 (define (/gen-record-argbuf-ifld f sfmt)
308 (string-append " " (gen-ifld-argbuf-ref f)
309 " = " (gen-extracted-ifld-value f) ";\n")
312 ; Return three of arguments to TRACE:
313 ; string argument to fprintf, character indicating type of third arg, value.
314 ; The type is one of: x.
316 (define (/gen-trace-argbuf-ifld f sfmt)
318 ; FIXME: Add method to return fprintf format string.
319 ", \"" (gen-sym f) " 0x%x\""
321 ", " (gen-extracted-ifld-value f))
324 ; Instruction field extraction support cont'd.
327 ; gen-extract method.
328 ; For the default case we use the ifield as is, which is output elsewhere.
331 <hardware-base> 'gen-extract
332 (lambda (self op sfmt local?)
336 ; gen-trace-extract method.
337 ; Return appropriate arguments for TRACE_EXTRACT.
340 <hardware-base> 'gen-trace-extract
341 (lambda (self op sfmt)
345 ; Extract the necessary fields into ARGBUF.
348 <hw-register> 'gen-extract
349 (lambda (self op sfmt local?)
350 (if (hw-cache-addr? self)
353 (gen-hw-index-argbuf-name (op:index op))
354 (gen-hw-index-argbuf-ref (op:index op)))
356 (gen-cpu-ref (hw-isas self) (gen-sym (op:type op)))
357 (gen-array-ref (gen-extracted-ifld-value (op-ifield op)))
362 ; Return appropriate arguments for TRACE_EXTRACT.
365 <hw-register> 'gen-trace-extract
366 (lambda (self op sfmt)
367 (if (hw-cache-addr? self)
369 ; FIXME: Add method to return fprintf format string.
370 ", \"" (gen-sym op) " 0x%x\""
372 ", " (gen-extracted-ifld-value (op-ifield op)))
376 ; Extract the necessary fields into ARGBUF.
379 <hw-address> 'gen-extract
380 (lambda (self op sfmt local?)
383 (gen-hw-index-argbuf-name (op:index op))
384 (gen-hw-index-argbuf-ref (op:index op)))
386 (gen-extracted-ifld-value (op-ifield op))
390 ; Return appropriate arguments for TRACE_EXTRACT.
393 <hw-address> 'gen-trace-extract
394 (lambda (self op sfmt)
396 ; FIXME: Add method to return fprintf format string.
397 ", \"" (gen-sym op) " 0x%x\""
399 ", " (gen-extracted-ifld-value (op-ifield op))))
402 ; Instruction field extraction support cont'd.
405 ; Return C code to record the field for the semantic handler.
406 ; In the case of a register, this is usually the address of the register's
407 ; value (if CACHE-ADDR).
408 ; LOCAL? indicates whether to record the value in a local variable or in
410 ; ??? Later allow target to provide an `extract' expression.
412 (define (/gen-op-extract op sfmt local?)
413 (send (op:type op) 'gen-extract op sfmt local?)
416 ; Return three of arguments to TRACE_EXTRACT:
417 ; string argument to fprintf, character indicating type of third arg, value.
418 ; The type is one of: x.
420 (define (/gen-op-trace-extract op sfmt)
421 (send (op:type op) 'gen-trace-extract op sfmt)
424 ; Return C code to define local vars to hold processed ifield data for
426 ; This is used when !with-scache.
427 ; Definitions of the extracted ifields is handled elsewhere.
429 (define (gen-sfmt-op-argbuf-defns sfmt)
430 (let ((operands (sfmt-extracted-operands sfmt)))
431 (logit 3 "sfmt = " (obj:name sfmt) " operands=" (string-map obj:name operands))
432 (string-list-map (lambda (op)
433 (let ((var-spec (sfmt-op-sbuf-elm op sfmt)))
444 ; Return C code to assign values to the local vars that hold processed ifield
445 ; data for <sformat> SFMT.
446 ; This is used when !with-scache.
447 ; Assignment of the extracted ifields is handled elsewhere.
449 (define (gen-sfmt-op-argbuf-assigns sfmt)
450 (let ((operands (sfmt-extracted-operands sfmt)))
451 (string-list-map (lambda (op)
452 (/gen-op-extract op sfmt #t))
456 ; Instruction field extraction support cont'd.
457 ; Emit extraction section of decode function.
459 ; Return C code to record insn field data for <sformat> SFMT.
460 ; This is used when with-scache.
462 (define (/gen-record-args sfmt)
463 (let ((operands (sfmt-extracted-operands sfmt))
464 (iflds (sfmt-needed-iflds sfmt)))
466 " /* Record the fields for the semantic handler. */\n"
467 (string-list-map (lambda (f) (/gen-record-argbuf-ifld f sfmt))
469 (string-list-map (lambda (op) (/gen-op-extract op sfmt #f))
471 " if (UNLIKELY(current_cpu->trace_extract_p))\n"
473 " current_cpu->trace_stream \n"
474 " << \"0x\" << hex << pc << dec << \" (" (gen-sym sfmt) ")\\t\"\n"
475 ; NB: The following is not necessary any more, as the ifield list
476 ; is a subset of the operand list.
477 ; (string-list-map (lambda (f)
479 ; " << \" " (gen-sym f) ":0x\" << hex << " (gen-sym f) " << dec\n"))
481 (string-list-map (lambda (ifld)
483 " << \" " (gen-extracted-ifld-value ifld) ":0x\" << hex << "
484 ; Add (SI) or (USI) cast for byte-wide data, to prevent C++ iostreams
485 ; from printing byte as plain raw char.
486 (cond ((not ifld) "")
487 ((mode:eq? 'QI (ifld-decode-mode ifld)) "(SI) ")
488 ((mode:eq? 'UQI (ifld-decode-mode ifld)) "(USI) ")
490 (gen-extracted-ifld-value ifld)
498 ; Return C code to record insn field data for profiling.
499 ; Also recorded are operands not mentioned in the fields but mentioned
500 ; in the semantic code.
502 ; FIXME: Register usage may need to be tracked as an array of longs.
503 ; If there are more than 32 regs, we can't know which until build time.
504 ; ??? For now we only handle reg sets of 32 or less.
506 ; ??? The other way to obtain register numbers is to defer computing them
507 ; until they're actually needed. It will speed up execution when not doing
508 ; profiling, though the speed up is only for the extraction phase.
509 ; On the other hand the current way has one memory reference per register
510 ; number in the profiling routines. For RISC this can be a lose, though for
511 ; more complicated instruction sets it could be a win as all the computation
512 ; is kept to the extraction phase. If someone wants to put forth some real
513 ; data, this might then be changed (or at least noted).
515 (define (/gen-record-profile-args sfmt)
516 (let ((in-ops (find op-profilable? (sfmt-in-ops sfmt)))
517 (out-ops (find op-profilable? (sfmt-out-ops sfmt)))
519 (if (or (not (with-any-profile?)) (and (null? in-ops) (null? out-ops)))
522 " /* Record the fields for profiling. */\n"
523 " if (UNLIKELY (current_cpu->trace_counter_p || current_cpu->final_insn_count_p))\n"
525 (string-list-map (lambda (op) (op:record-profile op sfmt #f))
527 (string-list-map (lambda (op) (op:record-profile op sfmt #t))
533 ; Return C code that extracts the fields of <sformat> SFMT.
535 ; Extraction is based on formats to reduce the amount of code generated.
536 ; However, we also need to emit code which records the hardware elements used
537 ; by the semantic code. This is currently done by recording this information
540 (define (/gen-extract-fn sfmt)
541 (logit 2 "Processing extractor for \"" (sfmt-key sfmt) "\" ...\n")
544 @prefix@_extract_" (gen-sym sfmt) " (@prefix@_scache* abuf, @cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn)"
546 " @prefix@_insn_word insn = "
547 (if (adata-integral-insn? CURRENT-ARCH)
550 (gen-define-field-macro sfmt)
551 (gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
553 (gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
555 (/gen-record-args sfmt)
557 (/gen-record-profile-args sfmt)
558 (gen-undef-field-macro sfmt)
563 ; For each format, return its extraction function.
565 (define (/define-all-extractor-fns)
566 (logit 2 "Processing extractor fn bodies ...\n")
567 (string-list-map /gen-extract-fn (current-sfmt-list))
570 (define (/declare-all-extractor-fns)
571 (logit 2 "Processing extractor fn declarations ...\n")
572 (string-map (lambda (sfmt)
575 @prefix@_extract_" (gen-sym sfmt) " (@prefix@_scache* abuf, @cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn);"))
580 ; Generate top level decoder.
581 ; INITIAL-BITNUMS is a target supplied list of bit numbers to use to
582 ; build the first decode table. If nil, we compute 8 bits of it (FIXME)
584 ; LSB0? is non-#f if bit number 0 is the least significant bit.
586 (define (/gen-decode-fn insn-list initial-bitnums lsb0?)
587 (assert (with-scache?))
589 ; Compute the initial DECODE-BITSIZE as the minimum of all insn lengths.
590 ; The caller of @prefix@_decode must fetch and pass exactly this number of bits
591 ; of the instruction.
592 ; ??? Make this a parameter later but only if necessary.
594 (let ((decode-bitsize (state-base-insn-bitsize)))
596 ; Compute INITIAL-BITNUMS if not supplied.
597 ; 0 is passed for the start bit (it is independent of lsb0?)
598 (if (null? initial-bitnums)
599 (set! initial-bitnums
600 (if (= 0 (length insn-list))
601 (list 0) ; dummy value
602 (decode-get-best-bits insn-list nil
608 ; All set. gen-decoder does the hard part, we just print out the result.
609 (let ((decode-code (gen-decoder insn-list initial-bitnums
612 (current-insn-lookup 'x-invalid #f)
617 // Declare extractor functions
619 /declare-all-extractor-fns
623 // Fetch & decode instruction
625 @prefix@_scache::decode (@cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn)
627 /* Result of decoder. */
628 @PREFIX@_INSN_TYPE itype;
631 @prefix@_insn_word insn = base_insn;
637 /* The instruction has been decoded and fields extracted. */
640 (if (state-conditional-exec?)
641 (let ((cond-ifld (current-ifld-lookup (car (isa-condition (current-isa))))))
644 (gen-ifld-extract-decl cond-ifld " " #f)
645 (gen-ifld-extract cond-ifld " "
646 (state-base-insn-bitsize)
647 (state-base-insn-bitsize)
649 " this->cond = " (gen-sym cond-ifld) ";\n"
655 // FIXME: To be redone (to handle ISA variants).
656 this->idesc = & @prefix@_idesc::idesc_table[itype];
657 // ??? record semantic handler?
658 assert(this->idesc->sem_index == itype);
663 /define-all-extractor-fns
667 ; Entry point. Generate decode.h.
669 (define (cgen-decode.h)
670 (logit 1 "Generating " (gen-cpu-name) "-decode.h ...\n")
674 ; Turn parallel execution support on if cpu needs it.
675 (set-with-parallel?! (state-parallel-exec?))
678 (gen-c-copyright "Decode header for @prefix@."
679 copyright-red-hat package-red-hat-simulators)
681 #ifndef @PREFIX@_DECODE_H
682 #define @PREFIX@_DECODE_H
688 // forward declaration of struct in -defs.h
697 using namespace cgen;
698 using namespace @arch@;
700 typedef UINT @prefix@_insn_word;
703 (lambda () (gen-cpu-insn-enum-decl (current-cpu)
704 (non-multi-insns (non-alias-insns (current-insn-list)))))
709 } // end @cpu@ namespace
712 ; ??? The semantic functions could go in the cpu's namespace.
713 ; There's no pressing need for it though.
719 #endif /* @PREFIX@_DECODE_H */\n"
723 ; Entry point. Generate decode.cxx.
725 (define (cgen-decode.cxx)
726 (logit 1 "Generating " (gen-cpu-name) "-decode.cxx ...\n")
730 ; Turn parallel execution support on if cpu needs it.
731 (set-with-parallel?! (state-parallel-exec?))
733 ; Tell the rtx->c translator we are the simulator.
734 (rtl-c-config! #:rtl-cover-fns? #t)
737 (gen-c-copyright "Simulator instruction decoder for @prefix@."
738 copyright-red-hat package-red-hat-simulators)
742 #include \"config.h\"
746 using namespace @cpu@; // FIXME: namespace organization still wip
749 (lambda () (/gen-decode-insn-globals (non-multi-insns (non-alias-insns (current-insn-list)))))
750 /gen-virtual-insn-finder
751 (lambda () (/gen-decode-fn (real-insns (current-insn-list))
752 (state-decode-assist)
753 (current-arch-insn-lsb0?)))