1 ; Macro instruction definitions.
2 ; Copyright (C) 2000, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4 ; See file COPYING.CGEN for details.
7 ; If the macro expands to a string, arguments in the input string
8 ; are refered to with %N. Multiple insns are separated with '\n'.
9 ; String expansion is a special case of the normal form which is a Scheme
10 ; expression that controls the expansion. The Scheme expression will be able
11 ; to refer to the current assembly state to decide how to perform the
12 ; expansion. Special expression `emit' is used to call the assembler emitter
13 ; for a particular insn. Special expression `expand' is used to return a
14 ; string to be reparsed (which is special cased).
16 ; Parse a list of macro-instruction expansion descriptions.
17 ; This is the main routine for building an minsn-expansion object from a
18 ; description in the .cpu file.
19 ; All arguments are in raw (non-evaluated) form.
21 ; ??? At present we only support macros that are aliases of one real insn.
23 ; Object to describe a macro-insn.
26 (class-make '<macro-insn>
31 ; list of expansion expressions
37 (method-make-make! <macro-insn>
38 '(location name comment attrs syntax expansions))
42 (define minsn-syntax (elm-make-getter <macro-insn> 'syntax))
43 (define minsn-expansions (elm-make-getter <macro-insn> 'expansions))
45 ; Return a list of the machs that support MINSN.
47 (define (minsn-machs minsn)
51 ; Return macro-instruction mnemonic.
52 ; This is computed from the syntax string.
54 (define minsn-mnemonic insn-mnemonic)
56 ; Return enum cgen_minsn_types value for MINSN.
58 (define (minsn-enum minsn)
59 (string-upcase (string-append "@ARCH@_MINSN_" (gen-sym minsn)))
62 ; Parse a macro-insn expansion description.
63 ; ??? At present we only support unconditional simple expansion.
65 (define (/minsn-parse-expansion context expn)
66 (if (not (form? expn))
67 (parse-error context "invalid macro expansion" expn))
68 (if (not (eq? 'emit (car expn)))
69 (parse-error context "invalid macro expansion, must be `(emit ...)'" expn))
73 ; Parse a macro-instruction description.
74 ; This is the main routine for building a macro-insn object from a
75 ; description in the .cpu file.
76 ; All arguments are in raw (non-evaluated) form.
77 ; The result is the parsed object or #f if object isn't for selected mach(s).
79 (define (/minsn-parse context name comment attrs syntax expansions)
80 (logit 2 "Processing macro-insn " name " ...\n")
82 (if (not (list? expansions))
83 (parse-error context "invalid macro expansion list" expansions))
85 ;; Pick out name first to augment the error context.
86 (let* ((name (parse-name context name))
87 (context (context-append-name context name))
88 (atlist-obj (atlist-parse context attrs "cgen_minsn")))
90 (if (keep-atlist? atlist-obj #f)
92 (let ((result (make <macro-insn>
93 (context-location context)
95 (parse-comment context comment)
97 (parse-syntax context syntax)
98 (map (lambda (e) (/minsn-parse-expansion context e))
103 (logit 2 "Ignoring " name ".\n")
107 ; Read a macro-insn description
108 ; This is the main routine for analyzing macro-insns in the .cpu file.
109 ; CONTEXT is a <context> object for error messages.
110 ; ARG-LIST is an associative list of field name and field value.
111 ; /minsn-parse is invoked to create the `macro-insn' object.
113 (define (/minsn-read context . arg-list)
122 ; Loop over each element in ARG-LIST, recording what's found.
123 (let loop ((arg-list arg-list))
126 (let ((arg (car arg-list))
127 (elm-name (caar arg-list)))
129 ((name) (set! name (cadr arg)))
130 ((comment) (set! comment (cadr arg)))
131 ((attrs) (set! attrs (cdr arg)))
132 ((syntax) (set! syntax (cadr arg)))
133 ((expansions) (set! expansions (cdr arg)))
134 (else (parse-error context "invalid macro-insn arg" arg)))
135 (loop (cdr arg-list)))))
137 ; Now that we've identified the elements, build the object.
138 (/minsn-parse context name comment attrs syntax expansions))
141 ; Define a macro-insn object, name/value pair list version.
145 (if (eq? APPLICATION 'SIMULATOR)
146 #f ; don't waste time if simulator
147 (let ((m (apply /minsn-read (cons (make-current-context "define-minsn")
150 (current-minsn-add! m))
154 ; Define a macro-insn object, all arguments specified.
155 ; This only supports one expansion.
156 ; Use define-minsn for the general case (??? which is of course not implemented
159 (define (define-full-minsn name comment attrs syntax expansion)
160 (if (eq? APPLICATION 'SIMULATOR)
161 #f ; don't waste time if simulator
162 (let ((m (/minsn-parse (make-current-context "define-full-minsn")
165 syntax (list expansion))))
167 (current-minsn-add! m))
171 ; Compute the ifield list for an alias macro-insn.
172 ; This involves making a copy of REAL-INSN's ifield list and assigning
173 ; known quantities to operands that have fixed values in the macro-insn.
175 (define (/minsn-compute-iflds context minsn-iflds real-insn)
176 (let* ((iflds (list-copy (insn-iflds real-insn)))
177 ; List of "free variables", i.e. operands.
178 (ifld-ops (find ifld-operand? iflds))
179 ; Names of fields in `ifld-ops'. As elements of minsn-iflds are
180 ; parsed the associated element in ifld-names is deleted. At the
181 ; end ifld-names must be empty. delq! can't delete the first
182 ; element in a list, so we insert a fencepost.
183 (ifld-names (cons #f (map obj:name ifld-ops)))
184 (isa-name-list (obj-isa-list real-insn)))
185 ;(logit 3 "Computing ifld list, operand field names: " ifld-names "\n")
186 ; For each macro-insn ifield expression, look it up in the real insn's
187 ; ifield list. If an operand without a prespecified value, leave
188 ; unchanged. If an operand or ifield with a value, assign the value to
190 (for-each (lambda (f)
191 (let* ((op-name (if (pair? f) (car f) f))
192 (op-obj (current-op-lookup op-name isa-name-list))
193 ; If `op-name' is an operand, use its ifield.
194 ; Otherwise `op-name' must be an ifield name.
196 (obj:name (hw-index:value (op:index op-obj)))
198 (ifld-pair (object-memq f-name iflds)))
199 ;(logit 3 "Processing ifield " f-name " ...\n")
201 (parse-error context "unknown operand" f))
202 ; Ensure `f' is an operand.
203 (if (not (memq f-name ifld-names))
204 (parse-error context "not an operand" f))
206 (set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
207 (delq! f-name ifld-names)))
209 (if (not (equal? ifld-names '(#f)))
210 (parse-error context "incomplete operand list, missing: " (cdr ifld-names)))
214 ; Create an aliased real insn from an alias macro-insn.
216 (define (minsn-make-alias context minsn)
217 (if (or (not (has-attr? minsn 'ALIAS))
218 ; Must emit exactly one real insn.
219 (not (eq? 'emit (caar (minsn-expansions minsn)))))
220 (parse-error context "not an alias macro-insn" minsn))
222 (let* ((expn (car (minsn-expansions minsn)))
223 (alias-of (current-insn-lookup (cadr expn) (obj-isa-list minsn))))
226 (parse-error context "unknown real insn in expansion" minsn))
228 (let ((i (make <insn>
229 (context-location context)
234 (/minsn-compute-iflds (context-append context
235 (string-append ": " (obj:str-name minsn)))
236 (cddr expn) alias-of)
237 #f ; ifield-assertion
241 ; FIXME: use same format entry as real insn,
242 ; build mask and test value at run time.
243 (insn-set-ifmt! i (ifmt-build i -1 #f (insn-iflds i))) ; (car (ifmt-analyze i #f))))
244 ;(insn-set-ifmt! i (insn-ifmt alias-of))
248 ; Called before a .cpu file is read in.
250 (define (minsn-init!)
251 (reader-add-command! 'define-minsn
253 Define a macro instruction, name/value pair list version.
255 nil 'arg-list define-minsn)
256 (reader-add-command! 'define-full-minsn
258 Define a macro instruction, all arguments specified.
260 nil '(name comment attrs syntax expansion)
266 ; Called after the .cpu file has been read in.
268 (define (minsn-finish!)