2 ; Copyright (C) 2000, 2002 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) ", "))
52 (string-append (-gen-write-fn-name sfmt) ", ")
54 "\"" (string-upcase name) "\", "
55 (gen-cpu-insn-enum (current-cpu) insn)
57 (gen-obj-attr-sid-defn 'insn insn all-attrs)
65 ; Return a function that lookups up virtual insns.
67 (define (-gen-virtual-insn-finder)
70 // Given a canonical virtual insn id, return the target specific one.
73 @prefix@_idesc::lookup_virtual (virtual_insn_type vit)
77 case VIRTUAL_INSN_INVALID: return @PREFIX@_INSN_X_INVALID;
82 case VIRTUAL_INSN_BEGIN: return @PREFIX@_INSN_X_BEGIN;
83 case VIRTUAL_INSN_CHAIN: return @PREFIX@_INSN_X_CHAIN;
84 case VIRTUAL_INSN_CTI_CHAIN: return @PREFIX@_INSN_X_CTI_CHAIN;
85 case VIRTUAL_INSN_BEFORE: return @PREFIX@_INSN_X_BEFORE;
86 case VIRTUAL_INSN_AFTER: return @PREFIX@_INSN_X_AFTER;
90 (state-conditional-exec?))
92 case VIRTUAL_INSN_COND: return @PREFIX@_INSN_X_COND;
94 ; Unused, but may still be requested. Just return X_INVALID.
96 case VIRTUAL_INSN_COND: return @PREFIX@_INSN_X_INVALID;
105 ; Return enum name of format FMT.
107 (define (-gen-fmt-enum fmt)
108 (string-upcase (gen-sym fmt))
111 ; Return names of semantic fns for INSN.
112 ; ??? Make global, call from gen-semantic-fn, blah blah blah.
114 (define (-gen-sem-fn-name insn)
115 (string-append "@prefix@_sem_" (gen-sym insn))
118 ; Return decls of each semantic fn.
120 (define (-gen-sem-fn-decls)
122 "// Decls of each semantic fn.\n\n"
123 "using @cpu@::@prefix@_sem_fn;\n"
124 (string-list-map (lambda (insn)
125 (string-list "extern @prefix@_sem_fn "
126 (-gen-sem-fn-name insn)
128 (scache-engine-insns))
134 ;; and the same for writeback functions
136 (define (-gen-write-fn-name sfmt)
137 (string-append "@prefix@_write_" (gen-sym sfmt))
141 (define (-gen-write-fn-decls)
143 "// Decls of each writeback fn.\n\n"
144 "using @cpu@::@prefix@_write_fn;\n"
145 (string-list-map (lambda (sfmt)
146 (string-list "extern @prefix@_write_fn "
147 (-gen-write-fn-name sfmt)
155 ; idesc, argbuf, and scache types
157 ; Generate decls for the insn descriptor table type IDESC.
159 (define (-gen-idesc-decls)
164 struct @prefix@_scache;
167 "struct @prefix@_parexec;\n" "")
169 "typedef void (@prefix@_sem_fn) (@cpu@_cpu* cpu, @prefix@_scache* sem, @prefix@_parexec* par_exec);"
170 "typedef sem_status (@prefix@_sem_fn) (@cpu@_cpu* cpu, @prefix@_scache* sem);")
173 "typedef sem_status (@prefix@_write_fn) (@cpu@_cpu* cpu, @prefix@_scache* sem, @prefix@_parexec* par_exec);"
177 // Instruction descriptor.
179 struct @prefix@_idesc {
184 // computed-goto label pointer (pbb engine)
185 // FIXME: frag case to be redone (should instead point to usage table).
186 cgoto_label cgoto;\n\n"
191 // scache engine executor for this insn
192 @prefix@_sem_fn* execute;\n\n"
197 // scache write executor for this insn
198 @prefix@_write_fn* writeback;\n\n"
202 const char* insn_name;
203 enum @prefix@_insn_type sem_index;
204 @arch@_insn_attr attrs;
206 // idesc table: indexed by sem_index
207 static @prefix@_idesc idesc_table[];
213 // semantic label pointers filled_in?
214 static bool idesc_table_initialized_p;\n"
219 static @prefix@_insn_type lookup_virtual (virtual_insn_type vit);
225 ; Utility of -gen-argbuf-fields-union to generate the definition for
226 ; <sformat-abuf> SBUF.
228 (define (-gen-argbuf-elm sbuf)
229 (logit 2 "Processing sbuf format " (obj:name sbuf) " ...\n")
231 " struct { /* " (obj:comment sbuf) " */\n"
232 (let ((elms (sbuf-elms sbuf)))
235 (string-list-map (lambda (elm)
242 " } " (gen-sym sbuf) ";\n")
245 ; Utility of -gen-scache-decls to generate the union of extracted ifields.
247 (define (-gen-argbuf-fields-union)
250 // Instruction argument buffer.
252 union @prefix@_sem_fields {\n"
253 (string-list-map -gen-argbuf-elm (current-sbuf-list))
255 // This one is for chain/cti-chain virtual insns.
257 // Number of insns in pbb.
259 // This is used by chain insns and by untaken conditional branches.
260 @prefix@_scache* next;
261 @prefix@_scache* branch_target;
263 // This one is for `before' virtual insns.
265 // The cache entry of the real insn.
266 @prefix@_scache* insn;
272 (define (-gen-scache-decls)
274 (-gen-argbuf-fields-union)
276 // Simulator instruction cache.
278 struct @prefix@_scache {
286 (if (state-conditional-exec?)
294 // PC of this instruction.
298 @prefix@_idesc* idesc;
301 @prefix@_sem_fields fields;
303 " (if (or (with-profile?) (with-parallel-write?))
306 // Only used if profiling or parallel execution support enabled during
308 unsigned long long written;
312 // decode given instruction
313 void decode (@cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn);
319 ; Instruction field extraction support.
320 ; Two implementations are provided, one for !with-scache and one for
323 ; Extracting ifields is a three phase process. First the ifields are
324 ; extracted and stored in local variables. Then any ifields requiring
325 ; additional processing for operands are handled. Then in the with-scache
326 ; case the results are stored in a struct for later retrieval by the semantic
329 ; The !with-scache case does this processing in the semantic function,
330 ; except it doesn't need the last step (it doesn't need to store the results
331 ; in a struct for later use).
333 ; The with-scache case extracts the ifields in the decode function.
334 ; Furthermore, we use <sformat-argbuf> to reduce the quantity of structures
335 ; created (this helps semantic-fragment pbb engines).
337 ; Return C code to record <ifield> F for the semantic handler
338 ; in a local variable rather than an ARGBUF struct.
340 (define (-gen-record-argbuf-ifld f sfmt)
341 (string-append " " (gen-ifld-argbuf-ref f)
342 " = " (gen-extracted-ifld-value f) ";\n")
345 ; Return three of arguments to TRACE:
346 ; string argument to fprintf, character indicating type of third arg, value.
347 ; The type is one of: x.
349 (define (-gen-trace-argbuf-ifld f sfmt)
351 ; FIXME: Add method to return fprintf format string.
352 ", \"" (gen-sym f) " 0x%x\""
354 ", " (gen-extracted-ifld-value f))
357 ; Instruction field extraction support cont'd.
360 ; gen-extract method.
361 ; For the default case we use the ifield as is, which is output elsewhere.
364 <hardware-base> 'gen-extract
365 (lambda (self op sfmt local?)
369 ; gen-trace-extract method.
370 ; Return appropriate arguments for TRACE_EXTRACT.
373 <hardware-base> 'gen-trace-extract
374 (lambda (self op sfmt)
378 ; Extract the necessary fields into ARGBUF.
381 <hw-register> 'gen-extract
382 (lambda (self op sfmt local?)
383 (if (hw-cache-addr? self)
386 (gen-hw-index-argbuf-name (op:index op))
387 (gen-hw-index-argbuf-ref (op:index op)))
389 (gen-cpu-ref (hw-isas self) (gen-sym (op:type op)))
390 (gen-array-ref (gen-extracted-ifld-value (op-ifield op)))
395 ; Return appropriate arguments for TRACE_EXTRACT.
398 <hw-register> 'gen-trace-extract
399 (lambda (self op sfmt)
400 (if (hw-cache-addr? self)
402 ; FIXME: Add method to return fprintf format string.
403 ", \"" (gen-sym op) " 0x%x\""
405 ", " (gen-extracted-ifld-value (op-ifield op)))
409 ; Extract the necessary fields into ARGBUF.
412 <hw-address> 'gen-extract
413 (lambda (self op sfmt local?)
416 (gen-hw-index-argbuf-name (op:index op))
417 (gen-hw-index-argbuf-ref (op:index op)))
419 (gen-extracted-ifld-value (op-ifield op))
423 ; Return appropriate arguments for TRACE_EXTRACT.
426 <hw-address> 'gen-trace-extract
427 (lambda (self op sfmt)
429 ; FIXME: Add method to return fprintf format string.
430 ", \"" (gen-sym op) " 0x%x\""
432 ", " (gen-extracted-ifld-value (op-ifield op))))
435 ; Instruction field extraction support cont'd.
438 ; Return C code to record the field for the semantic handler.
439 ; In the case of a register, this is usually the address of the register's
440 ; value (if CACHE-ADDR).
441 ; LOCAL? indicates whether to record the value in a local variable or in
443 ; ??? Later allow target to provide an `extract' expression.
445 (define (-gen-op-extract op sfmt local?)
446 (send (op:type op) 'gen-extract op sfmt local?)
449 ; Return three of arguments to TRACE_EXTRACT:
450 ; string argument to fprintf, character indicating type of third arg, value.
451 ; The type is one of: x.
453 (define (-gen-op-trace-extract op sfmt)
454 (send (op:type op) 'gen-trace-extract op sfmt)
457 ; Return C code to define local vars to hold processed ifield data for
459 ; This is used when !with-scache.
460 ; Definitions of the extracted ifields is handled elsewhere.
462 (define (gen-sfmt-op-argbuf-defns sfmt)
463 (let ((operands (sfmt-extracted-operands sfmt)))
464 (logit 3 "sfmt = " (obj:name sfmt) " operands=" (string-map obj:name operands))
465 (string-list-map (lambda (op)
466 (let ((var-spec (sfmt-op-sbuf-elm op sfmt)))
477 ; Return C code to assign values to the local vars that hold processed ifield
478 ; data for <sformat> SFMT.
479 ; This is used when !with-scache.
480 ; Assignment of the extracted ifields is handled elsewhere.
482 (define (gen-sfmt-op-argbuf-assigns sfmt)
483 (let ((operands (sfmt-extracted-operands sfmt)))
484 (string-list-map (lambda (op)
485 (-gen-op-extract op sfmt #t))
489 ; Instruction field extraction support cont'd.
490 ; Emit extraction section of decode function.
492 ; Return C code to record insn field data for <sformat> SFMT.
493 ; This is used when with-scache.
495 (define (-gen-record-args sfmt)
496 (let ((operands (sfmt-extracted-operands sfmt))
497 (iflds (sfmt-needed-iflds sfmt)))
499 " /* Record the fields for the semantic handler. */\n"
500 (string-list-map (lambda (f) (-gen-record-argbuf-ifld f sfmt))
502 (string-list-map (lambda (op) (-gen-op-extract op sfmt #f))
504 " if (UNLIKELY(current_cpu->trace_extract_p))\n"
506 " current_cpu->trace_stream \n"
507 " << \"0x\" << hex << pc << dec << \" (" (gen-sym sfmt) ")\\t\"\n"
508 ; NB: The following is not necessary any more, as the ifield list
509 ; is a subset of the operand list.
510 ; (string-list-map (lambda (f)
512 ; " << \" " (gen-sym f) ":0x\" << hex << " (gen-sym f) " << dec\n"))
514 (string-list-map (lambda (ifld)
516 " << \" " (gen-extracted-ifld-value ifld) ":0x\" << hex << "
517 ; Add (SI) or (USI) cast for byte-wide data, to prevent C++ iostreams
518 ; from printing byte as plain raw char.
519 (cond ((not ifld) "")
520 ((mode:eq? 'QI (ifld-decode-mode ifld)) "(SI) ")
521 ((mode:eq? 'UQI (ifld-decode-mode ifld)) "(USI) ")
523 (gen-extracted-ifld-value ifld)
531 ; Return C code to record insn field data for profiling.
532 ; Also recorded are operands not mentioned in the fields but mentioned
533 ; in the semantic code.
535 ; FIXME: Register usage may need to be tracked as an array of longs.
536 ; If there are more than 32 regs, we can't know which until build time.
537 ; ??? For now we only handle reg sets of 32 or less.
539 ; ??? The other way to obtain register numbers is to defer computing them
540 ; until they're actually needed. It will speed up execution when not doing
541 ; profiling, though the speed up is only for the extraction phase.
542 ; On the other hand the current way has one memory reference per register
543 ; number in the profiling routines. For RISC this can be a lose, though for
544 ; more complicated instruction sets it could be a win as all the computation
545 ; is kept to the extraction phase. If someone wants to put forth some real
546 ; data, this might then be changed (or at least noted).
548 (define (-gen-record-profile-args sfmt)
549 (let ((in-ops (find op-profilable? (sfmt-in-ops sfmt)))
550 (out-ops (find op-profilable? (sfmt-out-ops sfmt)))
552 (if (and (null? in-ops) (null? out-ops))
555 "#if WITH_PROFILE_MODEL_P\n"
556 " /* Record the fields for profiling. */\n"
557 " if (PROFILE_MODEL_P (current_cpu))\n"
559 (string-list-map (lambda (op) (op:record-profile op sfmt #f))
561 (string-list-map (lambda (op) (op:record-profile op sfmt #t))
568 ; Return C code that extracts the fields of <sformat> SFMT.
570 ; Extraction is based on formats to reduce the amount of code generated.
571 ; However, we also need to emit code which records the hardware elements used
572 ; by the semantic code. This is currently done by recording this information
575 (define (-gen-extract-fn sfmt)
576 (logit 2 "Processing extractor for \"" (sfmt-key sfmt) "\" ...\n")
579 @prefix@_extract_" (gen-sym sfmt) " (@prefix@_scache* abuf, @cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn)"
581 " @prefix@_insn_word insn = "
582 (if (adata-integral-insn? CURRENT-ARCH)
585 (gen-define-field-macro sfmt)
586 (gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
588 (gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
590 (-gen-record-args sfmt)
592 ;(-gen-record-profile-args sfmt) ??? not supported yet
593 (gen-undef-field-macro sfmt)
598 ; For each format, return its extraction function.
600 (define (-define-all-extractor-fns)
601 (logit 2 "Processing extractor fn bodies ...\n")
602 (string-list-map -gen-extract-fn (current-sfmt-list))
605 (define (-declare-all-extractor-fns)
606 (logit 2 "Processing extractor fn declarations ...\n")
607 (string-map (lambda (sfmt)
610 @prefix@_extract_" (gen-sym sfmt) " (@prefix@_scache* abuf, @cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn);"))
615 ; Generate top level decoder.
616 ; INITIAL-BITNUMS is a target supplied list of bit numbers to use to
617 ; build the first decode table. If nil, we compute 8 bits of it (FIXME)
619 ; LSB0? is non-#f if bit number 0 is the least significant bit.
620 ; FIXME: Need to be perfect for every subtable, or allow target more control.
621 ; Leave for later (and don't give target more control until oodles of effort
622 ; have been spent trying to be perfect! ... or close enough).
624 (define (-gen-decode-fn insn-list initial-bitnums lsb0?)
625 (assert (with-scache?))
627 ; Compute the initial DECODE-BITSIZE as the minimum of all insn lengths.
628 ; The caller of @prefix@_decode must fetch and pass exactly this number of bits
629 ; of the instruction.
630 ; ??? Make this a parameter later but only if necessary.
632 (let ((decode-bitsize (state-base-insn-bitsize)))
634 ; Compute INITIAL-BITNUMS if not supplied.
635 ; 0 is passed for the start bit (it is independent of lsb0?)
636 (if (null? initial-bitnums)
637 (set! initial-bitnums
638 (if (= 0 (length insn-list)) (list 0) ; dummy value
639 (decode-get-best-bits insn-list nil
645 ; All set. gen-decoder does the hard part, we just print out the result.
646 (let ((decode-code (gen-decoder insn-list initial-bitnums
649 (current-insn-lookup 'x-invalid)
654 // Declare extractor functions
656 -declare-all-extractor-fns
660 // Fetch & decode instruction
662 @prefix@_scache::decode (@cpu@_cpu* current_cpu, PCADDR pc, @prefix@_insn_word base_insn, @prefix@_insn_word entire_insn)
664 /* Result of decoder. */
665 @PREFIX@_INSN_TYPE itype;
668 @prefix@_insn_word insn = base_insn;
674 /* The instruction has been decoded and fields extracted. */
677 (if (state-conditional-exec?)
678 (let ((cond-ifld (current-ifld-lookup (car (isa-condition (current-isa))))))
681 (gen-ifld-extract-decl cond-ifld " " #f)
682 (gen-ifld-extract cond-ifld " "
683 (state-base-insn-bitsize)
684 (state-base-insn-bitsize)
686 " this->cond = " (gen-sym cond-ifld) ";\n"
692 // FIXME: To be redone (to handle ISA variants).
693 this->idesc = & @prefix@_idesc::idesc_table[itype];
694 // ??? record semantic handler?
695 assert(this->idesc->sem_index == itype);
700 -define-all-extractor-fns
704 ; Entry point. Generate decode.h.
706 (define (cgen-decode.h)
707 (logit 1 "Generating " (gen-cpu-name) " decode.h ...\n")
711 ; Turn parallel execution support on if cpu needs it.
712 (set-with-parallel?! (state-parallel-exec?))
715 (gen-copyright "Decode header for @prefix@."
716 copyright-red-hat package-red-hat-simulators)
718 #ifndef @PREFIX@_DECODE_H
719 #define @PREFIX@_DECODE_H
723 using namespace cgen;
724 using namespace @arch@;
726 typedef UINT @prefix@_insn_word;
729 (lambda () (gen-cpu-insn-enum-decl (current-cpu)
730 (non-multi-insns (non-alias-insns (current-insn-list)))))
735 } // end @cpu@ namespace
738 ; ??? The semantic functions could go in the cpu's namespace.
739 ; There's no pressing need for it though.
749 #endif /* @PREFIX@_DECODE_H */\n"
753 ; Entry point. Generate decode.cxx.
755 (define (cgen-decode.cxx)
756 (logit 1 "Generating " (gen-cpu-name) " decode.cxx ...\n")
760 ; Turn parallel execution support on if cpu needs it.
761 (set-with-parallel?! (state-parallel-exec?))
763 ; Tell the rtx->c translator we are the simulator.
764 (rtl-c-config! #:rtl-cover-fns? #t)
767 (gen-copyright "Simulator instruction decoder for @prefix@."
768 copyright-red-hat package-red-hat-simulators)
773 using namespace @cpu@; // FIXME: namespace organization still wip
776 (lambda () (-gen-decode-insn-globals (non-multi-insns (non-alias-insns (current-insn-list)))))
777 -gen-virtual-insn-finder
778 (lambda () (-gen-decode-fn (non-multi-insns (real-insns (current-insn-list)))
779 (state-decode-assist)
780 (current-arch-insn-lsb0?)))