1 ; Simulator generator support routines.
2 ; Copyright (C) 2000, 2001, 2002, 2006, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
5 ; One goal of this file is to provide cover functions for all methods.
6 ; i.e. this file fills in the missing pieces of the interface between
7 ; the application independent part of CGEN (i.e. the code loaded by read.scm)
8 ; and the application dependent part (i.e. sim-*.scm).
9 ; `send' is not intended to appear in sim-*.scm.
10 ; [It still does but that's to be fixed.]
12 ; Specify which application.
13 (set! APPLICATION 'SIMULATOR)
15 ; Cover functions for various methods.
17 ; Return the C type of something. This isn't always a mode.
19 (define (gen-type self) (send self 'gen-type))
21 ; Return the C type of an index's value or #f if not needed (scalar).
23 (define (gen-index-type op sfmt)
24 (let ((index-mode (send op 'get-index-mode)))
26 (mode:c-type index-mode)
32 ; Currently supported options:
34 ; generate code to use the scache
35 ; This is an all or nothing option, either scache is used or it's not.
37 ; generate code to do profiling in the semantic function
38 ; code (fn) or in the semantic switch (sw)
40 ; For architectures that have parallel execution.
41 ; Execute the semantics by recording the results in a generic buffer,
42 ; and doing a post-semantics writeback pass.
44 ; Only generate parallel versions of each insn.
46 ; Enable multiple-isa support (eg. arm+thumb).
47 ; copyright fsf|redhat
48 ; emit an FSF or Cygnus copyright (temporary, pending decision)
49 ; package gnusim|cygsim
50 ; indicate the software package
52 ; #t if the scache is being used
53 (define /with-scache? #f)
54 (define (with-scache?) /with-scache?)
56 ; #t if we're generating profiling code
57 ; Each of the function and switch semantic code can have profiling.
58 ; The options as passed are stored in /with-profile-{fn,sw}?, and
59 ; /with-profile? is set at code generation time.
60 (define /with-profile-fn? #f)
61 (define /with-profile-sw? #f)
62 (define /with-profile? #f)
63 (define (with-profile?) /with-profile?)
64 (define (with-any-profile?) (or /with-profile-fn? /with-profile-sw?))
66 ; #t if multiple isa support is enabled
67 (define /with-multiple-isa? #f)
68 (define (with-multiple-isa?) /with-multiple-isa?)
70 ; Handle parallel execution with generic writeback pass.
71 (define /with-generic-write? #f)
72 (define (with-generic-write?) /with-generic-write?)
74 ; Only generate parallel versions of each insn.
75 (define /with-parallel-only? #f)
76 (define (with-parallel-only?) /with-parallel-only?)
78 ; String containing copyright text.
79 (define CURRENT-COPYRIGHT #f)
81 ; String containing text defining the package we're generating code for.
82 (define CURRENT-PACKAGE #f)
84 ; Initialize the options.
86 (define (option-init!)
87 (set! /with-scache? #f)
88 (set! /with-profile-fn? #f)
89 (set! /with-profile-sw? #f)
90 (set! /with-multiple-isa? #f)
91 (set! /with-generic-write? #f)
92 (set! /with-parallel-only? #f)
93 (set! CURRENT-COPYRIGHT copyright-fsf)
94 (set! CURRENT-PACKAGE package-gnu-simulators)
98 ; Handle an option passed in from the command line.
100 (define (option-set! name value)
102 ((with-scache) (set! /with-scache? #t))
103 ((with-profile) (cond ((equal? value '("fn"))
104 (set! /with-profile-fn? #t))
105 ((equal? value '("sw"))
106 (set! /with-profile-sw? #t))
107 (else (error "invalid with-profile value" value))))
108 ((with-multiple-isa) (set! /with-multiple-isa? #t))
109 ((with-generic-write) (set! /with-generic-write? #t))
110 ((with-parallel-only) (set! /with-parallel-only? #t))
111 ((copyright) (cond ((equal? value '("fsf"))
112 (set! CURRENT-COPYRIGHT copyright-fsf))
113 ((equal? value '("redhat"))
114 (set! CURRENT-COPYRIGHT copyright-red-hat))
115 (else (error "invalid copyright value" value))))
116 ((package) (cond ((equal? value '("gnusim"))
117 (set! CURRENT-PACKAGE package-gnu-simulators))
118 ((equal? value '("cygsim"))
119 (set! CURRENT-PACKAGE package-red-hat-simulators))
120 (else (error "invalid package value" value))))
121 (else (error "unknown option" name))
126 ; #t if the cpu can execute insns parallely.
127 ; This one isn't passed on the command line, but we follow the convention
128 ; of prefixing these things with `with-'.
129 ; While processing operand reading (or writing), parallel execution support
130 ; needs to be turned off, so it is up to the appropriate cgen-foo.c proc to
131 ; set-with-parallel?! appropriately.
132 (define /with-parallel? #f)
133 (define (with-parallel?) /with-parallel?)
134 (define (set-with-parallel?! flag) (set! /with-parallel? flag))
136 ; Kind of parallel support.
137 ; If 'read, read pre-processing is done.
138 ; If 'write, write post-processing is done.
139 ; ??? At present we always use write post-processing, though the previous
140 ; version used read pre-processing. Not sure supporting both is useful
142 (define /with-parallel-kind 'write)
143 ; #t if parallel support is provided by read pre-processing.
144 (define (with-parallel-read?)
145 (and /with-parallel? (eq? /with-parallel-kind 'read))
147 ; #t if parallel support is provided by write post-processing.
148 (define (with-parallel-write?)
149 (and /with-parallel? (eq? /with-parallel-kind 'write))
154 ; All machine generated cpu elements are accessed through a cover macro
155 ; to hide the details of the underlying implementation.
157 (define c-cpu-macro "CPU")
159 (define (gen-cpu-ref sym)
160 (string-append c-cpu-macro " (" sym ")")
164 ; Return C code to fetch a value from instruction memory.
165 ; PC-VAR is the C expression containing the address of the start of the
167 ; ??? Aligned/unaligned support?
169 (define (gen-ifetch pc-var bitoffset bitsize)
170 (string-append "GETIMEM"
175 (else (error "bad bitsize argument to gen-ifetch" bitsize)))
177 pc-var " + " (number->string (quotient bitoffset 8))
181 ; Instruction field support code.
183 ; Return a <c-expr> object of the value of an ifield.
185 (define (/cxmake-ifld-val mode f)
187 ; ??? Perhaps a better way would be to defer evaluating the src of a
188 ; set until the method processing the dest.
189 (cx:make-with-atlist mode (gen-ifld-argbuf-ref f)
190 (atlist-make "" (bool-attr-make 'CACHED #t)))
191 (cx:make mode (gen-extracted-ifld-value f)))
197 ; gen-type - return C code representing the type
198 ; gen-sym-defn - generate decl using the provided symbol
199 ; gen-sym-get-macro - generate GET macro for accessing CPU elements
200 ; gen-sym-set-macro - generate SET macro for accessing CPU elements
206 (lambda (self) (mode:c-type (elm-get self 'mode)))
210 <scalar> 'gen-sym-defn
211 (lambda (self sym comment)
213 " /* " comment " */\n"
214 " " (send self 'gen-type) " "
215 (gen-c-symbol sym) ";\n"))
219 <scalar> 'gen-sym-get-macro
220 (lambda (self sym comment)
221 (let ((sym (gen-c-symbol sym)))
222 (gen-get-macro sym "" (gen-cpu-ref sym))))
226 <scalar> 'gen-sym-set-macro
227 (lambda (self sym comment)
228 (let ((sym (gen-c-symbol sym)))
229 (gen-set-macro sym "" (gen-cpu-ref sym))))
232 (method-make! <scalar> 'gen-ref (lambda (self sym index estate) sym))
238 (lambda (self) (mode:c-type (elm-get self 'mode)))
242 <array> 'gen-sym-defn
243 (lambda (self sym comment)
245 " /* " comment " */\n"
246 " " (send self 'gen-type) " "
248 (gen-array-ref (elm-get self 'dimensions))
254 <array> 'gen-sym-get-macro
255 (lambda (self sym comment)
256 (let ((sym (gen-c-symbol sym))
257 (rank (length (elm-get self 'dimensions))))
259 "#define GET_" (string-upcase sym)
260 "(" (string-drop 2 (gen-macro-args rank)) ") "
261 (gen-cpu-ref sym) (gen-array-ref (macro-args rank)) "\n"
266 <array> 'gen-sym-set-macro
267 (lambda (self sym comment)
268 (let ((sym (gen-c-symbol sym))
269 (rank (length (elm-get self 'dimensions))))
271 "#define SET_" (string-upcase sym)
272 "(" (string-drop 2 (gen-macro-args rank)) ", x) "
273 "(" (gen-cpu-ref sym) (gen-array-ref (macro-args rank))
278 ; Return a reference to the array.
279 ; SYM is the name of the array.
280 ; INDEX is either a single index object or a (possibly empty) list of objects,
281 ; one object per dimension.
285 (lambda (self sym index estate)
286 (let ((gen-index1 (lambda (idx)
288 (/gen-hw-index idx estate)
291 (cond ((list? index) (string-map gen-index1 index))
292 (else (gen-index1 index))))))
298 ; <integer> 'gen-type
300 ; (mode:c-type (mode-find (elm-get self 'bits)
301 ; (if (has-attr? self 'UNSIGNED)
306 ;(method-make! <integer> 'gen-sym-defn (lambda (self sym comment) ""))
307 ;(method-make! <integer> 'gen-sym-get-macro (lambda (self sym comment) ""))
308 ;(method-make! <integer> 'gen-sym-set-macro (lambda (self sym comment) ""))
310 ; Hardware descriptions support code.
312 ; Various operations are required for each h/w object to support the various
313 ; things the simulator will want to do with it.
316 ; gen-type - C type to use to record value, as a string.
317 ; ??? Delete and just use get-mode?
318 ; gen-defn - generate a definition of the h/w element
319 ; gen-get-macro - Generate definition of the GET access macro.
320 ; gen-set-macro - Generate definition of the SET access macro.
321 ; gen-write - Same as gen-read except done on output operands
322 ; cxmake-get - Return a <c-expr> object to fetch the value.
323 ; gen-set-quiet - Set the value.
324 ; ??? Could just call this gen-set as there is no gen-set-trace
325 ; but for consistency with the messages passed to operands
327 ; save-index? - return #t if an index needs to be saved for parallel
328 ; execution post-write processing
333 ; gen-sym-get-macro - Generate default GET access macro.
334 ; gen-sym-set-macro - Generate default SET access macro.
335 ; gen-ref - Return a C reference to the object.
337 ; gen-type handler, must be overridden.
340 <hardware-base> 'gen-type
341 (lambda (self) (error "gen-type not overridden:" self))
344 ; Generate CPU state struct entries, must be overridden.
347 <hardware-base> 'gen-defn
348 (lambda (self) (error "gen-defn not overridden:" self))
351 (method-make! <hardware-base> 'gen-sym-decl (lambda (self sym comment) ""))
353 ; Return a C reference to a hardware object.
355 (method-make! <hardware-base> 'gen-ref (lambda (self sym index estate) sym))
357 ; Each hardware type must provide its own gen-write method.
360 <hardware-base> 'gen-write
361 (lambda (self estate index mode sfmt op access-macro)
362 (error "gen-write method not overridden:" self))
365 (method-make! <hardware-base> 'gen-profile-decl (lambda (self) ""))
367 ; Default gen-record-profile method.
370 <hardware-base> 'gen-record-profile
371 (lambda (self index sfmt estate)
375 ; Default cxmake-get method.
376 ; Return a <c-expr> object of the value of SELF.
377 ; ESTATE is the current rtl evaluator state.
378 ; INDEX is a <hw-index> object. It must be an ifield.
379 ; SELECTOR is a hardware selector RTX.
382 <hardware-base> 'cxmake-get
383 (lambda (self estate mode index selector)
384 (if (not (eq? 'ifield (hw-index:type index)))
385 (error "not an ifield hw-index" index))
386 (/cxmake-ifld-val mode (hw-index:value index)))
389 ; Handle gen-get-macro/gen-set-macro.
392 <hardware-base> 'gen-get-macro
398 <hardware-base> 'gen-set-macro
405 ; 'gen-set-quiet helper for PC values.
406 ; NEWVAL is a <c-expr> object of the value to be assigned.
407 ; If OPTIONS contains #:direct, set the PC directly, bypassing semantic
408 ; code considerations.
409 ; ??? OPTIONS support wip. Probably want a new form (or extend existing form)
410 ; of rtx: that takes a variable number of named arguments.
411 ; ??? Another way to get #:direct might be (raw-reg h-pc).
413 (define (/hw-gen-set-quiet-pc self estate mode index selector newval . options)
414 (if (not (send self 'pc?)) (error "Not a PC:" self))
415 (cond ((memq #:direct options)
416 (/hw-gen-set-quiet self estate mode index selector newval))
417 ((has-attr? newval 'CACHED)
418 (string-append "SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, "
422 (string-append "SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, "
427 (method-make! <hw-pc> 'gen-set-quiet /hw-gen-set-quiet-pc)
429 ; Handle updates of the pc during parallel execution.
430 ; This is done in a post-processing pass after semantic evaluation.
431 ; SFMT is the <sformat>.
433 ; ACCESS-MACRO is the runtime C macro to use to fetch indices computed
434 ; during semantic evaluation.
436 ; ??? This wouldn't be necessary if gen-set-quiet were a virtual method.
437 ; At this point I'm reluctant to willy nilly make methods virtual.
441 (lambda (self estate index mode sfmt op access-macro)
443 (send self 'gen-set-quiet estate VOID index hw-selector-default
444 (cx:make DFLT (string-append access-macro
445 " (" (gen-sym op) ")")))))
450 (lambda (self estate yes?)
452 (string-append "if ("
455 " SEM_SKIP_INSN (current_cpu, sem_arg, vpc);\n")))
460 (method-make-forward! <hw-register> 'type '(gen-type))
463 <hw-register> 'gen-defn
465 (send (elm-get self 'type) 'gen-sym-defn (obj:name self) (obj:comment self)))
468 (method-make-forward! <hw-register> 'type '(gen-ref
472 ; For parallel instructions supported by queueing outputs for later update,
473 ; return a boolean indicating if an index needs to be recorded.
474 ; An example of when the index isn't needed is if the index can be determined
478 <hw-register> 'save-index?
480 ; FIXME: Later handle case where register number is determined at runtime.
484 ; Handle updates of registers during parallel execution.
485 ; This is done in a post-processing pass after semantic evaluation.
486 ; SFMT is the <sformat>.
487 ; OP is the <operand>.
488 ; ACCESS-MACRO is the runtime C macro to use to fetch indices computed
489 ; during semantic evaluation.
490 ; FIXME: May need mode of OP.
493 <hw-register> 'gen-write
494 (lambda (self estate index mode sfmt op access-macro)
495 ; First get a hw-index object to use during indexing.
496 ; Some indices, e.g. memory addresses, are computed during semantic
497 ; evaluation. Others are computed during the extraction phase.
498 (let ((index (send index 'get-write-index self sfmt op access-macro)))
500 (send self 'gen-set-quiet estate mode index hw-selector-default
501 (cx:make DFLT (string-append access-macro
502 " (" (gen-sym op) ")"))))))
506 <hw-register> 'gen-profile-decl
509 " /* " (obj:comment self) " */\n"
510 " unsigned long " (gen-c-symbol (obj:name self)) ";\n"))
514 <hw-register> 'gen-record-profile
515 (lambda (self index sfmt estate)
516 ; FIXME: Need to handle scalars.
517 (/gen-hw-index-raw index estate))
521 <hw-register> 'gen-get-macro
523 (let ((getter (elm-get self 'get))
524 (mode (send self 'get-mode)))
526 (let ((args (car getter))
527 (expr (cadr getter)))
528 (gen-get-macro2 (gen-sym self)
529 (if (hw-scalar? self) "" "index")
531 #f ;; h/w is not ISA-specific
532 (if (hw-scalar? self)
534 (list (list (car args) 'UINT "index")))
536 #:rtl-cover-fns? #t #:macro? #t)))
537 (send self 'gen-sym-get-macro
538 (obj:name self) (obj:comment self)))))
542 <hw-register> 'gen-set-macro
544 (let ((setter (elm-get self 'set))
545 (mode (send self 'get-mode)))
547 (let ((args (car setter))
548 (expr (cadr setter)))
549 (gen-set-macro2 (gen-sym self)
550 (if (hw-scalar? self) "" "index")
552 (rtl-c VOID ;; not `mode', sets have mode VOID
553 #f ;; h/w is not ISA-specific
554 (if (hw-scalar? self)
555 (list (list (car args) (hw-mode self) "(x)"))
556 (list (list (car args) 'UINT "(index)")
557 (list (cadr args) (hw-mode self) "(x)")))
559 #:rtl-cover-fns? #t #:macro? #t)))
560 (send self 'gen-sym-set-macro
561 (obj:name self) (obj:comment self)))))
564 ; Utility to build a <c-expr> object to fetch the value of a register.
566 (define (/hw-cxmake-get hw estate mode index selector)
567 (let ((mode (if (mode:eq? 'DFLT mode)
570 (getter (hw-getter hw)))
571 ; If the register is accessed via a cover function/macro, do it.
572 ; Otherwise fetch the value from the cached address or from the CPU struct.
575 (let ((scalar? (hw-scalar? hw))
576 (c-index (/gen-hw-index index estate)))
577 (string-append "GET_"
578 (string-upcase (gen-sym hw))
580 (if scalar? "" c-index)
582 ((and (hw-cache-addr? hw) ; FIXME: redo test
583 (eq? 'ifield (hw-index:type index)))
587 (gen-hw-index-argbuf-ref index)
588 (gen-hw-index-argbuf-name index))))
589 (else (gen-cpu-ref (send hw 'gen-ref
590 (gen-sym hw) index estate))))))
593 (method-make! <hw-register> 'cxmake-get /hw-cxmake-get)
596 ; ??? raw-reg: support is wip
599 <hw-register> 'cxmake-get-raw
600 (lambda (self estate mode index selector)
601 (let ((mode (if (mode:eq? 'DFLT mode)
602 (send self 'get-mode)
604 (cx:make mode (gen-cpu-ref (send self 'gen-ref
605 (gen-sym self) index estate)))))
608 ; Utilities to generate C code to assign a variable to a register.
610 (define (/hw-gen-set-quiet hw estate mode index selector newval)
611 (let ((setter (hw-setter hw)))
613 (let ((scalar? (hw-scalar? hw))
614 (c-index (/gen-hw-index index estate)))
615 (string-append "SET_"
616 (string-upcase (gen-sym hw))
618 (if scalar? "" (string-append c-index ", "))
621 ((and (hw-cache-addr? hw) ; FIXME: redo test
622 (eq? 'ifield (hw-index:type index)))
625 (gen-hw-index-argbuf-ref index)
626 (gen-hw-index-argbuf-name index))
627 " = " (cx:c newval) ";\n"))
628 (else (string-append (gen-cpu-ref (send hw 'gen-ref
629 (gen-sym hw) index estate))
630 " = " (cx:c newval) ";\n"))))
633 (method-make! <hw-register> 'gen-set-quiet /hw-gen-set-quiet)
639 <hw-register> 'gen-set-quiet-raw
640 (lambda (self estate mode index selector newval)
641 (string-append (gen-cpu-ref (send self 'gen-ref
642 (gen-sym self) index estate))
643 " = " (cx:c newval) ";\n"))
646 ; Return name of C access function for getting/setting a register.
648 (define (gen-reg-getter-fn hw prefix)
649 (string-append prefix "_" (gen-sym hw) "_get")
652 (define (gen-reg-setter-fn hw prefix)
653 (string-append prefix "_" (gen-sym hw) "_set")
656 ; Generate decls for access fns of register HW, beginning with
657 ; PREFIX, using C type TYPE.
658 ; SCALAR? is #t if the register is a scalar. Otherwise it is #f and the
659 ; register is a bank of registers.
661 (define (gen-reg-access-decl hw prefix type scalar?)
664 (gen-reg-getter-fn hw prefix)
666 (if scalar? "" ", UINT")
669 (gen-reg-setter-fn hw prefix)
671 (if scalar? "" "UINT, ")
676 ; Generate defns of access fns of register HW, beginning with
677 ; PREFIX, using C type TYPE.
678 ; SCALAR? is #t if the register is a scalar. Otherwise it is #f and the
679 ; register is a bank of registers.
680 ; GET/SET-CODE are C fragments to get/set the value.
681 ; ??? Inlining left for later.
683 (define (gen-reg-access-defn hw prefix type scalar? get-code set-code)
685 "/* Get the value of " (obj:str-name hw) ". */\n\n"
687 (gen-reg-getter-fn hw prefix)
688 " (SIM_CPU *current_cpu"
689 (if scalar? "" ", UINT regno")
693 "/* Set a value for " (obj:str-name hw) ". */\n\n"
695 (gen-reg-setter-fn hw prefix)
696 " (SIM_CPU *current_cpu, "
697 (if scalar? "" "UINT regno, ")
707 <hw-memory> 'cxmake-get
708 (lambda (self estate mode index selector)
709 (let ((mode (if (mode:eq? 'DFLT mode)
712 (default-selector? (hw-selector-default? selector)))
714 (string-append "GETMEM" (obj:str-name mode)
715 (if default-selector? "" "ASI")
718 (/gen-hw-index index estate)
719 (if default-selector?
722 (/gen-hw-selector selector)))
727 <hw-memory> 'gen-set-quiet
728 (lambda (self estate mode index selector newval)
729 (let ((mode (if (mode:eq? 'DFLT mode)
732 (default-selector? (hw-selector-default? selector)))
733 (string-append "SETMEM" (obj:str-name mode)
734 (if default-selector? "" "ASI")
737 (/gen-hw-index index estate)
738 (if default-selector?
741 (/gen-hw-selector selector)))
742 ", " (cx:c newval) ");\n")))
745 (method-make-forward! <hw-memory> 'type '(gen-type))
746 (method-make! <hw-memory> 'gen-defn (lambda (self sym comment) ""))
747 (method-make! <hw-memory> 'gen-sym-get-macro (lambda (self sym comment) ""))
748 (method-make! <hw-memory> 'gen-sym-set-macro (lambda (self sym comment) ""))
750 ; For parallel instructions supported by queueing outputs for later update,
751 ; return the type of the index or #f if not needed.
754 <hw-memory> 'save-index?
756 ; In the case of the complete memory address being an immediate
757 ; argument, we can return #f (later).
762 <hw-memory> 'gen-write
763 (lambda (self estate index mode sfmt op access-macro)
764 (let ((index (send index 'get-write-index self sfmt op access-macro)))
766 (send self 'gen-set-quiet estate mode index
768 (cx:make DFLT (string-append access-macro " ("
773 ; Immediates, addresses.
775 (method-make-forward! <hw-immediate> 'type '(gen-type))
778 <hw-immediate> 'gen-defn
780 (send (elm-get self 'type) 'gen-sym-defn (obj:name self) (obj:comment self)))
783 (method-make-forward! <hw-immediate> 'type '(gen-sym-get-macro
787 <hw-immediate> 'gen-write
788 (lambda (self estate index mode sfmt op access-macro)
789 (error "gen-write of <hw-immediate> shouldn't happen"))
793 (method-make! <hw-address> 'gen-type (lambda (self) "ADDR"))
794 (method-make! <hw-address> 'gen-defn (lambda (self sym comment) ""))
795 (method-make! <hw-address> 'gen-sym-get-macro (lambda (self sym comment) ""))
796 (method-make! <hw-address> 'gen-sym-set-macro (lambda (self sym comment) ""))
798 ; Return a <c-expr> object of the value of SELF.
799 ; ESTATE is the current rtl evaluator state.
800 ; INDEX is a hw-index object. It must be an ifield.
801 ; Needed because we record our own copy of the ifield in ARGBUF.
802 ; SELECTOR is a hardware selector RTX.
805 <hw-address> 'cxmake-get
806 (lambda (self estate mode index selector)
807 (if (not (eq? 'ifield (hw-index:type index)))
808 (error "not an ifield hw-index" index))
810 (cx:make mode (gen-hw-index-argbuf-ref index))
811 (cx:make mode (gen-hw-index-argbuf-name index))))
815 <hw-address> 'gen-write
816 (lambda (self estate index mode sfmt op access-macro)
817 (error "gen-write of <hw-address> shouldn't happen"))
820 ;; FIXME: consistency says there should be gen-defn, gen-sym-[gs]et-macro
821 (method-make! <hw-iaddress> 'gen-type (lambda (self) "IADDR"))
823 ; Return a <c-expr> object of the value of SELF.
824 ; ESTATE is the current rtl evaluator state.
825 ; INDEX is a <hw-index> object. It must be an ifield.
826 ; Needed because we record our own copy of the ifield in ARGBUF,
827 ; *and* because we want to record in the result the 'CACHED attribute
828 ; since instruction addresses based on ifields are fixed [and thus cacheable].
829 ; SELECTOR is a hardware selector RTX.
832 <hw-iaddress> 'cxmake-get
833 (lambda (self estate mode index selector)
834 (if (not (eq? 'ifield (hw-index:type index)))
835 (error "not an ifield hw-index" index))
837 ; ??? Perhaps a better way would be to defer evaluating the src of a
838 ; set until the method processing the dest.
839 (cx:make-with-atlist mode (gen-hw-index-argbuf-ref index)
840 (atlist-make "" (bool-attr-make 'CACHED #t)))
841 (cx:make mode (gen-hw-index-argbuf-name index))))
844 ; Hardware index support code.
846 ; Return the index to use by the gen-write method.
847 ; In the cases where this is needed (the index isn't known until insn
848 ; execution time), the index is computed along with the value to be stored,
852 <hw-index> 'get-write-index
853 (lambda (self hw sfmt op access-macro)
854 (if (memq (hw-index:type self) '(scalar constant enum str-expr ifield))
856 (let ((index-mode (send hw 'get-index-mode)))
858 (make <hw-index> 'anonymous 'str-expr index-mode
859 (string-append access-macro " (" (/op-index-name op) ")"))
860 (hw-index-scalar)))))
863 ; Return the name of the PAREXEC structure member holding a hardware index
866 (define (/op-index-name op)
867 (string-append (gen-sym op) "_idx")
870 ; Cover fn to hardware indices to generate the actual C code.
871 ; INDEX is the hw-index object (i.e. op:index).
872 ; The result is a string of C code.
875 (define (/gen-hw-index-raw index estate)
876 (let ((type (hw-index:type index))
877 (mode (hw-index:mode index))
878 (value (hw-index:value index)))
881 ; special case UINT to cut down on unnecessary verbosity.
882 ; ??? May wish to handle more similarily.
883 ((constant) (if (mode:eq? 'UINT mode)
884 (number->string value)
885 (string-append "((" (mode:c-type mode) ") "
886 (number->string value)
888 ((enum) (let ((sym (hw-index-enum-name index))
889 (obj (hw-index-enum-obj index)))
890 (gen-enum-sym obj sym)))
892 ((rtx) (rtl-c-with-estate estate mode value))
893 ((ifield) (if (= (ifld-length value) 0)
895 (gen-extracted-ifld-value value)))
896 ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
897 (op:selector value) #f)))
898 (else (error "/gen-hw-index-raw: invalid index:" index))))
901 ; Same as /gen-hw-index-raw except used where speedups are possible.
902 ; e.g. doing array index calcs at extraction time.
904 (define (/gen-hw-index index estate)
905 (let ((type (hw-index:type index))
906 (mode (hw-index:mode index))
907 (value (hw-index:value index)))
910 ((constant) (string-append "((" (mode:c-type mode) ") "
911 (number->string value)
913 ((enum) (let ((sym (hw-index-enum-name index))
914 (obj (hw-index-enum-obj index)))
915 (gen-enum-sym obj sym)))
917 ((rtx) (rtl-c-with-estate estate mode value))
918 ((ifield) (if (= (ifld-length value) 0)
920 (cx:c (/cxmake-ifld-val mode value))))
921 ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
922 (op:selector value))))
923 (else (error "/gen-hw-index: invalid index:" index))))
926 ; Return address where HW is stored.
928 (define (/gen-hw-addr hw estate index)
929 (let ((setter (hw-setter hw)))
930 (cond ((and (hw-cache-addr? hw) ; FIXME: redo test
931 (eq? 'ifield (hw-index:type index)))
933 (gen-hw-index-argbuf-ref index)
934 (gen-hw-index-argbuf-name index)))
937 (gen-cpu-ref (send hw 'gen-ref
938 (gen-sym hw) index estate))))))
941 ; Return a <c-expr> object of the value of a hardware index.
944 <hw-index> 'cxmake-get
945 (lambda (self estate mode)
946 (let ((mode (if (mode:eq? 'DFLT mode) (elm-get self 'mode) mode)))
947 ; If MODE is VOID, abort.
948 (if (mode:eq? 'VOID mode)
949 (error "hw-index:cxmake-get: result needs a mode" self))
950 (cx:make (if (mode:host? mode)
951 ; FIXME: Temporary hack to generate same code as before.
952 (let ((xmode (object-copy-top mode)))
953 (obj-cons-attr! xmode (bool-attr-make 'FORCE-C #t))
956 (/gen-hw-index self estate))))
959 ; Hardware selector support code.
961 ; Generate C code for SEL.
963 (define (/gen-hw-selector sel)
964 (rtl-c INT #f nil sel)
967 ; Instruction operand support code.
970 ; gen-type - Return C type to use to hold operand's value.
971 ; gen-read - Record an operand's value prior to parallely executing
972 ; several instructions. Not used if gen-write used.
973 ; gen-write - Write back an operand's value after parallely executing
974 ; several instructions. Not used if gen-read used.
975 ; cxmake-get - Return C code to fetch the value of an operand.
976 ; gen-set-quiet - Return C code to set the value of an operand.
977 ; gen-set-trace - Return C code to set the value of an operand, and print
978 ; a result trace message. ??? Ideally this will go away when
979 ; trace record support is complete.
981 ; Return the C type of an operand.
982 ; Generally we forward things on to TYPE, but for the actual type we need to
983 ; use the get-mode method.
985 ;(method-make-forward! <operand> 'type '(gen-type))
989 ; First get the mode.
990 (let ((mode (send self 'get-mode)))
991 ; If it's VOID use the type's type.
992 (if (mode:eq? 'DFLT mode)
993 (send (op:type self) 'gen-type)
994 (mode:c-type mode))))
997 ; Extra pc operand methods.
1001 (lambda (self estate mode index selector)
1002 (let ((mode (if (mode:eq? 'DFLT mode)
1003 (send self 'get-mode)
1006 (logit 4 "<pc> cxmake-get self=" (obj:name self) " mode=" (obj:name mode) "\n")
1008 (if (obj-has-attr? self 'RAW)
1009 (let ((hw (op:type self))
1010 ;; For consistency with <operand> process index,selector similarly.
1011 (index (if index index (op:index self)))
1012 (selector (if selector selector (op:selector self))))
1013 (send hw 'cxmake-get-raw estate mode index selector))
1014 ;; The enclosing function must set `pc' to the correct value.
1015 (cx:make mode "pc"))))
1020 (lambda (self estate yes?)
1021 (send (op:type self) 'cxmake-skip estate
1022 (rtl-c INT (obj-isa-list self) nil yes? #:rtl-cover-fns? #t)))
1025 ; For parallel write post-processing, we don't want to defer setting the pc.
1026 ; ??? Not sure anymore.
1028 ; <pc> 'gen-set-quiet
1029 ; (lambda (self estate mode index selector newval)
1030 ; (/op-gen-set-quiet self estate mode index selector newval)))
1032 ; <pc> 'gen-set-trace
1033 ; (lambda (self estate mode index selector newval)
1034 ; (/op-gen-set-trace self estate mode index selector newval)))
1036 ; Name of C macro to access parallel execution operand support.
1038 (define /par-operand-macro "OPRND")
1040 ; Return C code to fetch an operand's value and save it away for the
1041 ; semantic handler. This is used to handle parallel execution of several
1042 ; instructions where all inputs of all insns are read before any outputs are
1044 ; For operands, the word `read' is only used in this context.
1046 (define (op:read op sfmt)
1047 (let ((estate (estate-make-for-rtl-c nil)))
1048 (send op 'gen-read estate sfmt /par-operand-macro))
1051 ; Return C code to write an operand's value.
1052 ; This is used to handle parallel execution of several instructions where all
1053 ; outputs are written to temporary spots first, and then a final
1054 ; post-processing pass is run to update cpu state.
1055 ; For operands, the word `write' is only used in this context.
1057 (define (op:write op sfmt)
1058 (let ((estate (estate-make-for-rtl-c nil)))
1059 (send op 'gen-write estate sfmt /par-operand-macro))
1062 ; Default gen-read method.
1063 ; This is used to help support targets with parallel insns.
1064 ; Either this or gen-write (but not both) is used.
1068 (lambda (self estate sfmt access-macro)
1073 ; Pass #f for the index -> use the operand's builtin index.
1074 ; Ditto for the selector.
1075 (cx:c (send self 'cxmake-get estate DFLT #f #f))
1079 ; Forward gen-write onto the <hardware> object.
1082 <operand> 'gen-write
1083 (lambda (self estate sfmt access-macro)
1084 (let ((write-back-code (send (op:type self) 'gen-write estate
1085 (op:index self) (op:mode self)
1086 sfmt self access-macro)))
1087 ; If operand is conditionally written, we have to check that first.
1088 ; ??? If two (or more) operands are written based on the same condition,
1089 ; all the tests can be collapsed together. Not sure that's a big
1092 (string-append " if (written & (1 << "
1093 (number->string (op:num self))
1101 ; Return <c-expr> object to get the value of an operand.
1102 ; ESTATE is the current rtl evaluator state.
1103 ; If INDEX is non-#f use it, otherwise use (op:index self).
1104 ; This special handling of #f for INDEX is *only* supported for operands
1105 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1106 ; Ditto for SELECTOR.
1109 <operand> 'cxmake-get
1110 (lambda (self estate mode index selector)
1111 (let ((mode (if (mode:eq? 'DFLT mode)
1112 (send self 'get-mode)
1114 (index (if index index (op:index self)))
1115 (selector (if selector selector (op:selector self))))
1116 ;; If the instruction could be parallely executed with others and we're
1117 ;; doing read pre-processing, the operand has already been fetched, we
1118 ;; just have to grab the cached value.
1120 (cond ((obj-has-attr? self 'RAW)
1121 (send (op:type self) 'cxmake-get-raw estate mode index selector))
1122 ((with-parallel-read?)
1123 (cx:make-with-atlist mode
1124 (string-append /par-operand-macro
1125 " (" (gen-sym self) ")")
1126 nil)) ;; FIXME: want CACHED attr if present
1128 (let ((args (car (op:getter self)))
1129 (expr (cadr (op:getter self))))
1132 (if (= (length args) 0)
1134 (list (list (car args) 'UINT index)))
1136 #:rtl-cover-fns? #t)))
1138 (send (op:type self) 'cxmake-get estate mode index selector)))))
1140 (logit 4 "<operand> cxmake-get self=" (obj:name self) " mode=" (obj:name mode)
1141 " index=" (obj:name index) " selector=" selector "\n")
1146 ; Utilities to implement gen-set-quiet/gen-set-trace.
1148 (define (/op-gen-set-quiet op estate mode index selector newval)
1149 (send (op:type op) 'gen-set-quiet estate mode index selector newval)
1152 ; Return C code to call the appropriate queued-write handler.
1155 (define (/op-gen-queued-write op estate mode index selector newval)
1156 (let* ((hw (op:type op))
1157 (setter (hw-setter hw))
1158 (sem-mode (mode:sem-mode mode)))
1162 ; FIXME: clean up (pc? op) vs (memory? hw)
1163 ; FIXME: (send 'pc?) is a temporary hack, (pc? op) didn't work
1164 (cond ((send hw 'pc?)
1180 (string-downcase (symbol->string (if sem-mode
1181 (mode-real-name sem-mode)
1182 (mode-real-name mode)))))))
1183 "_write (current_cpu"
1184 ; ??? May need to include h/w id some day.
1186 (string-append ", " (gen-reg-setter-fn hw "@cpu@"))
1188 (cond ((hw-scalar? hw)
1191 (string-append ", " (/gen-hw-index index estate)))
1193 (string-append ", " (/gen-hw-index index estate)))
1195 (string-append ", " (/gen-hw-addr (op:type op) estate index))))
1201 (define (/op-gen-set-quiet-parallel op estate mode index selector newval)
1202 (if (with-generic-write?)
1203 (/op-gen-queued-write op estate mode index selector (cx:c newval))
1205 (if (op-save-index? op)
1207 /par-operand-macro " (" (/op-index-name op) ")"
1208 " = " (/gen-hw-index index estate) ";\n")
1211 /par-operand-macro " (" (gen-sym op) ")"
1212 " = " (cx:c newval) ";\n"))
1215 (define /operand-number-elaboration-written? #f)
1217 ;; Return code to update `written'.
1219 (define (/op-gen-written-update op)
1221 ;; FIXME: we don't yet handle a large number of operands
1222 (if (< (op:num op) 32)
1223 (string-append " written |= (1 << "
1224 (number->string (op:num op))
1227 ;; FIXME: This creates broken simulators if with-parallel-write?.
1228 ;; (message (if (with-parallel-write?) "Error: " "Warning: ")
1230 ;; " operand number " (op:num op)
1231 ;; " is too large (>= 32)\n")
1232 (if (not /operand-number-elaboration-written?)
1234 (message "This is a current internal cgen limitation.\n")
1235 (if (not (with-parallel-write?))
1236 (message "The only effect is a loss in profiling capability.\n"))
1237 (set! /operand-number-elaboration-written? #t)))
1242 (define (/op-gen-set-trace op estate mode index selector newval)
1245 " " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1246 ; Dispatch to setter code if appropriate
1249 (let ((args (car (op:setter op)))
1250 (expr (cadr (op:setter op))))
1253 (if (= (length args) 0)
1254 (list (list 'newval mode "opval"))
1255 (list (list (car args) 'UINT index)
1256 (list 'newval mode "opval")))
1258 #:rtl-cover-fns? #t))
1260 (send (op:type op) 'gen-set-quiet estate mode index selector
1261 (cx:make-with-atlist mode "opval" (cx:atlist newval))))
1262 (/op-gen-written-update op)
1263 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1264 ; For each insn record array of operand numbers [or indices into
1265 ; operand instance table].
1266 ; Could just scan the operand table for the operand or hardware number,
1267 ; assuming the operand number is stored in `op'.
1268 " TRACE_RESULT (current_cpu, abuf"
1269 ", " (send op 'gen-pretty-name mode)
1270 ", " (mode:printf-type mode)
1275 (define (/op-gen-set-trace-parallel op estate mode index selector newval)
1278 " " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1279 (if (with-generic-write?)
1280 (/op-gen-queued-write op estate mode index selector "opval")
1282 (if (op-save-index? op)
1284 /par-operand-macro " (" (/op-index-name op) ")"
1285 " = " (/gen-hw-index index estate) ";\n")
1287 " " /par-operand-macro " (" (gen-sym op) ")"
1289 (/op-gen-written-update op)
1290 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1291 ; For each insn record array of operand numbers [or indices into
1292 ; operand instance table].
1293 ; Could just scan the operand table for the operand or hardware number,
1294 ; assuming the operand number is stored in `op'.
1295 " TRACE_RESULT (current_cpu, abuf"
1296 ", " (send op 'gen-pretty-name mode)
1297 ", " (mode:printf-type mode)
1302 ; Return C code to set the value of an operand.
1303 ; NEWVAL is a <c-expr> object of the value to store.
1304 ; If INDEX is non-#f use it, otherwise use (op:index self).
1305 ; This special handling of #f for INDEX is *only* supported for operands
1306 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1307 ; Ditto for SELECTOR.
1310 <operand> 'gen-set-quiet
1311 (lambda (self estate mode index selector newval)
1312 (let ((mode (if (mode:eq? 'DFLT mode)
1313 (send self 'get-mode)
1315 (index (if index index (op:index self)))
1316 (selector (if selector selector (op:selector self))))
1317 ; ??? raw-reg: support wip
1318 (cond ((obj-has-attr? self 'RAW)
1319 (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1320 ((with-parallel-write?)
1321 (/op-gen-set-quiet-parallel self estate mode index selector newval))
1323 (/op-gen-set-quiet self estate mode index selector newval)))))
1326 ; Return C code to set the value of an operand and print TRACE_RESULT message.
1327 ; NEWVAL is a <c-expr> object of the value to store.
1328 ; If INDEX is non-#f use it, otherwise use (op:index self).
1329 ; This special handling of #f for INDEX is *only* supported for operands
1330 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1331 ; Ditto for SELECTOR.
1334 <operand> 'gen-set-trace
1335 (lambda (self estate mode index selector newval)
1336 (let ((mode (if (mode:eq? 'DFLT mode)
1337 (send self 'get-mode)
1339 (index (if index index (op:index self)))
1340 (selector (if selector selector (op:selector self))))
1341 ; ??? raw-reg: support wip
1342 (cond ((obj-has-attr? self 'RAW)
1343 (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1344 ((with-parallel-write?)
1345 (/op-gen-set-trace-parallel self estate mode index selector newval))
1347 (/op-gen-set-trace self estate mode index selector newval)))))
1350 ; Define and undefine C macros to tuck away details of instruction format used
1351 ; in the parallel execution functions. See gen-define-field-macro for a
1352 ; similar thing done for extraction/semantic functions.
1354 (define (gen-define-parallel-operand-macro sfmt)
1355 (string-append "#define " /par-operand-macro "(f) "
1356 "par_exec->operands."
1361 (define (gen-undef-parallel-operand-macro sfmt)
1362 (string-append "#undef " /par-operand-macro "\n")
1365 ; Operand profiling and parallel execution support.
1368 <operand> 'save-index?
1369 (lambda (self) (send (op:type self) 'save-index? self))
1372 ; Return boolean indicating if operand OP needs its index saved
1373 ; (for parallel write post-processing support).
1375 (define (op-save-index? op)
1376 (send op 'save-index?)
1379 ; Return C code to record profile data for modeling use.
1380 ; In the case of a register, this is usually the register's number.
1381 ; This shouldn't be called in the case of a scalar, the code should be
1382 ; smart enough to know there is no need.
1384 (define (op:record-profile op sfmt out?)
1385 (let ((estate (estate-make-for-rtl-c nil)))
1386 (send op 'gen-record-profile sfmt out? estate))
1389 ; Return C code to record the data needed for profiling operand SELF.
1390 ; This is done during extraction.
1393 <operand> 'gen-record-profile
1394 (lambda (self sfmt out? estate)
1395 (if (hw-scalar? (op:type self))
1398 (gen-argbuf-ref (send self 'sbuf-profile-sym out?))
1400 (send (op:type self) 'gen-record-profile
1401 (op:index self) sfmt estate)
1405 ; Return C code to track profiling of operand SELF.
1406 ; This is usually called by the x-after handler.
1409 <operand> 'gen-profile-code
1410 (lambda (self insn out?)
1413 (if out? "set_" "get_")
1414 (gen-sym (op:type self))
1416 (if (hw-scalar? (op:type self))
1420 (send self 'sbuf-profile-sym out?))))
1424 ; CPU, mach, model support.
1426 ; Return the declaration of the cpu/insn enum.
1428 (define (gen-cpu-insn-enum-decl cpu insn-list)
1429 (gen-enum-decl "@prefix@_insn_type"
1430 "instructions in cpu family @cpu@"
1432 (append! (map (lambda (i)
1435 (atlist-attrs (obj-atlist i)))))
1437 (if (with-parallel?)
1441 (cons (symbol-append 'par- (obj:name i))
1443 (atlist-attrs (obj-atlist i))))
1444 (cons (symbol-append 'write- (obj:name i))
1446 (atlist-attrs (obj-atlist i))))))
1447 (parallel-insns insn-list)))
1452 ; Return the enum of INSN in cpu family CPU.
1453 ; In addition to CGEN_INSN_TYPE, an enum is created for each insn in each
1454 ; cpu family. This collapses the insn enum space for each cpu to increase
1455 ; cache efficiently (since the IDESC table is similarily collapsed).
1457 (define (gen-cpu-insn-enum cpu insn)
1458 (string-upcase (string-append "@PREFIX@_INSN_" (gen-sym insn)))
1461 ; Return C code to declare the machine data.
1463 (define (/gen-mach-decls)
1465 (string-map (lambda (mach)
1466 (gen-obj-sanitize mach
1467 (string-append "extern const MACH "
1470 (current-mach-list))
1474 ; Return C code to define the machine data.
1476 (define (/gen-mach-data)
1478 "const MACH *sim_machs[] =\n{\n"
1479 (string-map (lambda (mach)
1482 (string-append "#ifdef " (gen-have-cpu (mach-cpu mach)) "\n"
1483 " & " (gen-sym mach) "_mach,\n"
1485 (current-mach-list))
1491 ; Return C declarations of cpu model support stuff.
1492 ; ??? This goes in arch.h but a better place is each cpu.h.
1494 (define (/gen-arch-model-decls)
1496 (gen-enum-decl 'model_type "model types"
1498 (append (map (lambda (model)
1499 (cons (obj:name model)
1501 (atlist-attrs (obj-atlist model)))))
1502 (current-model-list))
1504 "#define MAX_MODELS ((int) MODEL_MAX)\n\n"
1505 (gen-enum-decl 'unit_type "unit types"
1509 ; "apply append" squeezes out nils.
1511 ; create <model_name>-<unit-name> for each unit
1512 (map (lambda (model)
1513 (let ((units (model:units model)))
1517 (cons (symbol-append (obj:name model) '-
1519 (cons '- (atlist-attrs (obj-atlist model)))))
1521 (current-model-list)))
1523 ; FIXME: revisit MAX_UNITS
1524 "#define MAX_UNITS ("
1527 (map (lambda (lengths) (apply max lengths))
1529 (let ((timing (insn-timing insn)))
1532 (map (lambda (insn-timing)
1533 (if (null? (cdr insn-timing))
1535 (length (timing:units (cdr insn-timing)))))
1537 (current-insn-list)))))
1544 (method-make! <unit> 'gen-decl (lambda (self) ""))
1546 ; Lookup operand named OP-NAME in INSN.
1547 ; Returns #f if OP-NAME is not an operand of INSN.
1548 ; IN-OUT is 'in to request an input operand, 'out to request an output operand,
1549 ; and 'in-out to request either (though if an operand is used for input and
1550 ; output then the input version is returned).
1551 ; FIXME: Move elsewhere.
1553 (define (insn-op-lookup op-name insn in-out)
1554 (letrec ((lookup (lambda (op-list)
1555 (cond ((null? op-list) #f)
1556 ((eq? op-name (op:sem-name (car op-list))) (car op-list))
1557 (else (lookup (cdr op-list)))))))
1559 ((in) (lookup (sfmt-in-ops (insn-sfmt insn))))
1560 ((out) (lookup (sfmt-out-ops (insn-sfmt insn))))
1561 ((in-out) (or (lookup (sfmt-in-ops (insn-sfmt insn)))
1562 (lookup (sfmt-out-ops (insn-sfmt insn)))))
1563 (else (error "insn-op-lookup: bad arg:" in-out))))
1566 ; Return C code to profile a unit's usage.
1567 ; UNIT-NUM is number of the unit in INSN.
1568 ; OVERRIDES is a list of (name value) pairs, where
1569 ; - NAME is a spec name, one of cycles, pred, in, out.
1570 ; The only ones we're concerned with are in,out. They map operand names
1571 ; as they appear in the semantic code to operand names as they appear in
1572 ; the function unit spec.
1573 ; - VALUE is the operand to NAME. For in,out it is (NAME VALUE) where
1574 ; - NAME is the name of an input/output arg of the unit.
1575 ; - VALUE is the name of the operand as it appears in semantic code.
1577 ; ??? This is a big sucker, though half of it is just the definitions
1581 <unit> 'gen-profile-code
1582 (lambda (self unit-num insn overrides cycles-var-name)
1584 (inputs (unit:inputs self))
1585 (outputs (unit:outputs self))
1587 ; Return C code to initialize UNIT-REFERENCED-VAR to be a bit mask
1588 ; of operands of UNIT that were read/written by INSN.
1589 ; INSN-REFERENCED-VAR is a bitmask of operands read/written by INSN.
1590 ; All we have to do is map INSN-REFERENCED-VAR to
1591 ; UNIT-REFERENCED-VAR.
1592 ; ??? For now we assume all input operands are read.
1593 (gen-ref-arg (lambda (arg num in-out)
1594 (let* ((op-name (assq-ref overrides (car arg)))
1595 (op (insn-op-lookup (if op-name
1599 (insn-referenced-var "insn_referenced")
1600 (unit-referenced-var "referenced"))
1607 (number->string (op:num op))
1611 (number->string num)
1616 (number->string num)
1620 ; Initialize unit argument ARG.
1621 ; OUT? is #f for input args, #t for output args.
1622 (gen-arg-init (lambda (arg out?)
1626 ; Ignore remapped arg, handled elsewhere.
1627 (assq (car arg) overrides)
1628 ; Ignore operands not in INSN.
1629 (not (insn-op-lookup (car arg) insn
1630 (if out? 'out 'in))))
1632 (let ((sym (gen-profile-sym (gen-c-symbol (car arg))
1637 (gen-argbuf-ref sym)
1640 ; Return C code to declare variable to hold unit argument ARG.
1641 ; OUT? is #f for input args, #t for output args.
1642 (gen-arg-decl (lambda (arg out?)
1643 (if (null? (cdr arg)) ; ignore scalars
1646 (mode:c-type (mode:lookup (cadr arg)))
1648 (gen-profile-sym (gen-c-symbol (car arg))
1651 (if (null? (cddr arg))
1653 (number->string (caddr arg)))
1656 ; Return C code to pass unit argument ARG to the handler.
1657 ; OUT? is #f for input args, #t for output args.
1658 (gen-arg-arg (lambda (arg out?)
1659 (if (null? (cdr arg)) ; ignore scalars
1662 (gen-profile-sym (gen-c-symbol (car arg))
1668 " int referenced = 0;\n"
1669 " int UNUSED insn_referenced = abuf->written;\n"
1670 ; Declare variables to hold unit arguments.
1671 (string-map (lambda (arg) (gen-arg-decl arg #f))
1673 (string-map (lambda (arg) (gen-arg-decl arg #t))
1675 ; Initialize 'em, being careful not to initialize an operand that
1677 (let (; Make a list of names of in/out overrides.
1678 (in-overrides (find-apply cadr
1679 (lambda (elm) (eq? (car elm) 'in))
1681 (out-overrides (find-apply cadr
1682 (lambda (elm) (eq? (car elm) 'out))
1685 (string-map (lambda (arg)
1686 (if (memq (car arg) in-overrides)
1688 (gen-arg-init arg #f)))
1690 (string-map (lambda (arg)
1691 (if (memq (car arg) out-overrides)
1693 (gen-arg-init arg #t)))
1695 (string-map (lambda (arg)
1702 (gen-profile-sym (gen-c-symbol (cadr arg)) #f)
1705 (gen-profile-sym (gen-c-symbol (caddr arg)) #f))
1711 (gen-profile-sym (gen-c-symbol (cadr arg)) #t)
1714 (gen-profile-sym (gen-c-symbol (caddr arg)) #t))
1718 (parse-error (make-prefix-context "insn function unit spec")
1719 "invalid spec" arg))))
1721 ; Create bitmask indicating which args were referenced.
1722 (string-map (lambda (arg num) (gen-ref-arg arg num 'in))
1724 (iota (length inputs)))
1725 (string-map (lambda (arg num) (gen-ref-arg arg num 'out))
1727 (iota (length outputs)
1729 ; Emit the call to the handler.
1730 " " cycles-var-name " += "
1731 (gen-model-unit-fn-name (unit:model self) self)
1732 " (current_cpu, idesc"
1733 ", " (number->string unit-num)
1735 (string-map (lambda (arg) (gen-arg-arg arg #f))
1737 (string-map (lambda (arg) (gen-arg-arg arg #t))
1744 ; Return C code to profile an insn-specific unit's usage.
1745 ; UNIT-NUM is number of the unit in INSN.
1748 <iunit> 'gen-profile-code
1749 (lambda (self unit-num insn cycles-var-name)
1750 (let ((args (iunit:args self))
1751 (unit (iunit:unit self)))
1752 (send unit 'gen-profile-code unit-num insn args cycles-var-name)))
1755 ; ARGBUF generation.
1756 ; ARGBUF support is put in cpuall.h, which doesn't depend on sim-cpu.scm,
1757 ; so this support is here.
1759 ; Utility of /gen-argbuf-fields-union to generate the definition for
1760 ; <sformat-abuf> SBUF.
1762 (define (/gen-argbuf-elm sbuf)
1763 (logit 2 "Processing sbuf format " (obj:name sbuf) " ...\n")
1765 " struct { /* " (obj:comment sbuf) " */\n"
1766 (let ((elms (sbuf-elms sbuf)))
1769 (string-list-map (lambda (elm)
1776 " } " (gen-sym sbuf) ";\n")
1779 ; Utility of gen-argbuf-type to generate the union of extracted ifields.
1781 (define (/gen-argbuf-fields-union)
1784 /* Instruction argument buffer. */
1786 union sem_fields {\n"
1787 (string-list-map /gen-argbuf-elm (current-sbuf-list))
1790 /* Writeback handler. */
1792 /* Pointer to argbuf entry for insn whose results need writing back. */
1793 const struct argbuf *abuf;
1795 /* x-before handler */
1797 /*const SCACHE *insns[MAX_PARALLEL_INSNS];*/
1800 /* x-after handler */
1804 /* This entry is used to terminate each pbb. */
1806 /* Number of insns in pbb. */
1808 /* Next pbb to execute. */
1810 SCACHE *branch_target;
1817 ; Generate the definition of the structure that records arguments.
1818 ; This is a union of structures with one structure for each insn format.
1819 ; It also includes hardware profiling information and miscellaneous
1821 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1823 (define (gen-argbuf-type cpu-data?)
1824 (logit 2 "Generating ARGBUF type ...\n")
1826 (if (and cpu-data? (with-scache?))
1827 (/gen-argbuf-fields-union)
1829 (if cpu-data? "" "#ifndef WANT_CPU\n")
1831 /* The ARGBUF struct. */
1833 /* These are the baseclass definitions. */
1838 /* ??? Temporary hack for skip insns. */
1841 /* cpu specific data follows */\n"
1847 union sem_fields fields;\n"
1849 CGEN_INSN_WORD insn;
1853 (if cpu-data? "" "#endif\n")
1858 ; Generate the definition of the structure that records a cached insn.
1859 ; This is cpu family specific (member `argbuf' is) so it is machine generated.
1860 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1862 (define (gen-scache-type cpu-data?)
1863 (logit 2 "Generating SCACHE type ...\n")
1865 (if cpu-data? "" "#ifndef WANT_CPU\n")
1869 ??? SCACHE used to contain more than just argbuf. We could delete the
1870 type entirely and always just use ARGBUF, but for future concerns and as
1871 a level of abstraction it is left in. */
1874 struct argbuf argbuf;\n"
1875 (if (with-generic-write?) "\
1877 int last_insn_p;\n" "")
1879 (if cpu-data? "" "#endif\n")
1886 ; Generate a table of mode data.
1887 ; For now all we need is the names.
1889 (define (gen-mode-defs)
1891 "const char *mode_names[] = {\n"
1892 (string-map (lambda (m)
1893 (string-append " \"" (string-upcase (obj:str-name m)) "\",\n"))
1894 ; We don't treat aliases as being different from the real
1895 ; mode here, so ignore them.
1896 (mode-list-non-alias-values))
1901 ; Insn profiling support.
1903 ; Generate declarations for local variables needed for modelling code.
1906 <insn> 'gen-profile-locals
1907 (lambda (self model)
1908 ; (let ((cti? (or (has-attr? self 'UNCOND-CTI)
1909 ; (has-attr? self 'COND-CTI))))
1911 ; (if cti? " int UNUSED taken_p = 0;\n" "")
1916 ; Generate C code to profile INSN.
1919 <insn> 'gen-profile-code
1920 (lambda (self model cycles-var-name)
1922 (let ((timing (assq-ref (insn-timing self) (obj:name model))))
1924 (string-list-map (lambda (iunit unit-num)
1925 (send iunit 'gen-profile-code unit-num self cycles-var-name))
1926 (timing:units timing)
1927 (iota (length (timing:units timing))))
1928 (send (model-default-unit model) 'gen-profile-code 0 self nil cycles-var-name)))
1932 ; .cpu file loading support
1934 ; Only run sim-analyze-insns! once.
1935 (define /sim-insns-analyzed? #f)
1937 ; List of computed sformat argument buffers.
1938 (define /sim-sformat-abuf-list #f)
1939 (define (current-sbuf-list) /sim-sformat-abuf-list)
1941 ; Called before/after the .cpu file has been read in.
1944 (set! /sim-insns-analyzed? #f)
1945 (set! /sim-sformat-abuf-list #f)
1949 ;; Subroutine of /create-virtual-insns!.
1950 ;; Add virtual insn INSN to the database.
1951 ;; We put virtual insns ahead of normal insns because they're kind of special,
1952 ;; and it helps to see them first in lists.
1953 ;; ORDINAL is a used to place the insn ahead of normal insns;
1954 ;; it is a pair so we can do the update for the next virtual insn here.
1956 (define (/virtual-insn-add! ordinal insn)
1957 (obj-set-ordinal! insn (cdr ordinal))
1958 (current-insn-add! insn)
1959 (set-cdr! ordinal (- (cdr ordinal) 1))
1962 ; Create the virtual insns.
1964 (define (/create-virtual-insns!)
1965 (let ((all (all-isas-attr-value))
1966 (context (make-prefix-context "virtual insns"))
1967 ;; Record as a pair so /virtual-insn-add! can update it.
1968 (ordinal (cons #f -1)))
1974 '(comment "pbb begin handler")
1975 `(attrs VIRTUAL PBB (ISA ,@all))
1976 '(syntax "--begin--")
1977 '(semantics (c-code VOID "\
1979 #if WITH_SCACHE_PBB_@PREFIX@
1980 #if defined DEFINE_SWITCH || defined FAST_P
1981 /* In the switch case FAST_P is a constant, allowing several optimizations
1982 in any called inline functions. */
1983 vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1985 #if 0 /* cgen engine can't handle dynamic fast/full switching yet. */
1986 vpc = @prefix@_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu)));
1988 vpc = @prefix@_pbb_begin (current_cpu, 0);
2000 '(comment "pbb chain handler")
2001 `(attrs VIRTUAL PBB (ISA ,@all))
2002 '(syntax "--chain--")
2003 '(semantics (c-code VOID "\
2005 #if WITH_SCACHE_PBB_@PREFIX@
2006 vpc = @prefix@_pbb_chain (current_cpu, sem_arg);
2007 #ifdef DEFINE_SWITCH
2019 '(comment "pbb cti-chain handler")
2020 `(attrs VIRTUAL PBB (ISA ,@all))
2021 '(syntax "--cti-chain--")
2022 '(semantics (c-code VOID "\
2024 #if WITH_SCACHE_PBB_@PREFIX@
2025 #ifdef DEFINE_SWITCH
2026 vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
2027 pbb_br_type, pbb_br_npc);
2030 /* FIXME: Allow provision of explicit ifmt spec in insn spec. */
2031 vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
2032 CPU_PBB_BR_TYPE (current_cpu),
2033 CPU_PBB_BR_NPC (current_cpu));
2044 '(comment "pbb begin handler")
2045 `(attrs VIRTUAL PBB (ISA ,@all))
2046 '(syntax "--before--")
2047 '(semantics (c-code VOID "\
2049 #if WITH_SCACHE_PBB_@PREFIX@
2050 @prefix@_pbb_before (current_cpu, sem_arg);
2060 '(comment "pbb after handler")
2061 `(attrs VIRTUAL PBB (ISA ,@all))
2062 '(syntax "--after--")
2063 '(semantics (c-code VOID "\
2065 #if WITH_SCACHE_PBB_@PREFIX@
2066 @prefix@_pbb_after (current_cpu, sem_arg);
2076 '(comment "invalid insn handler")
2077 `(attrs VIRTUAL (ISA ,@all))
2078 '(syntax "--invalid--")
2079 (list 'semantics (list 'c-code 'VOID (string-append "\
2081 /* Update the recorded pc in the cpu state struct.
2082 Only necessary for WITH_SCACHE case, but to avoid the
2083 conditional compilation .... */
2085 /* Virtual insns have zero size. Overwrite vpc with address of next insn
2086 using the default-insn-bitsize spec. When executing insns in parallel
2087 we may want to queue the fault and continue execution. */
2088 vpc = SEM_NEXT_VPC (sem_arg, pc, " (number->string (bits->bytes (state-default-insn-bitsize))) ");
2089 vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
2096 (define (sim-finish!)
2097 ; Add begin,chain,before,after,invalid handlers if not provided.
2098 ; The code generators should first look for x-foo-@prefix@, then for x-foo.
2099 ; ??? This is good enough for the first pass. Will eventually need to use
2100 ; less C and more RTL.
2101 (/create-virtual-insns!)
2106 ; Called after file is read in and global error checks are done
2107 ; to initialize tables.
2109 (define (sim-analyze!)
2113 ; Scan insns, analyzing semantics and computing instruction formats.
2114 ; 'twould be nice to do this in sim-analyze! but it doesn't know whether this
2115 ; needs to be done or not (which is determined by what files are being
2116 ; generated). Since this is an expensive operation, we defer doing this
2117 ; to the files that need it.
2119 (define (sim-analyze-insns!)
2120 ; This can only be done if one isa and one cpu family is being kept.
2123 (if (not /sim-insns-analyzed?)
2126 (arch-analyze-insns! CURRENT-ARCH
2127 #f ; don't include aliases
2128 #t) ; do analyze the semantics
2130 ; Compute the set of sformat argument buffers.
2131 (set! /sim-sformat-abuf-list (compute-sformat-argbufs! (current-sfmt-list)))
2133 (set! /sim-insns-analyzed? #t)))
2135 ; Do our own error checking.
2136 (assert (current-insn-lookup 'x-invalid #f))
2143 (define (cgen-all-arch)
2154 (define (cgen-all-cpu)