1 ; Macro instruction definitions.
2 ; Copyright (C) 2000 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
39 (define minsn-syntax (elm-make-getter <macro-insn> 'syntax))
40 (define minsn-expansions (elm-make-getter <macro-insn> 'expansions))
42 ; Return a list of the machs that support MINSN.
44 (define (minsn-machs minsn)
48 ; Return macro-instruction mnemonic.
49 ; This is computed from the syntax string.
51 (define minsn-mnemonic insn-mnemonic)
53 ; Return enum cgen_minsn_types value for MINSN.
55 (define (minsn-enum minsn)
56 (string-upcase (string-append "@ARCH@_MINSN_" (gen-sym minsn)))
59 ; Parse a macro-insn expansion description.
60 ; ??? At present we only support unconditional simple expansion.
62 (define (-minsn-parse-expansion errtxt expn)
63 (if (not (form? expn))
64 (parse-error errtxt "invalid macro expansion" expn))
65 (if (not (eq? 'emit (car expn)))
66 (parse-error errtxt "invalid macro expansion, must be `(emit ...)'" expn))
70 ; Parse a macro-instruction description.
71 ; This is the main routine for building a macro-insn object from a
72 ; description in the .cpu file.
73 ; All arguments are in raw (non-evaluated) form.
74 ; The result is the parsed object or #f if object isn't for selected mach(s).
76 (define (-minsn-parse errtxt name comment attrs syntax expansions)
77 (logit 2 "Processing macro-insn " name " ...\n")
79 (if (not (list? expansions))
80 (parse-error errtxt "invalid macro expansion list" expansions))
82 (let ((name (parse-name name errtxt))
83 (atlist-obj (atlist-parse attrs "cgen_minsn" errtxt)))
85 (if (keep-atlist? atlist-obj #f)
87 (let ((result (make <macro-insn>
89 (parse-comment comment errtxt)
91 (parse-syntax syntax errtxt)
92 (map (lambda (e) (-minsn-parse-expansion errtxt e))
97 (logit 2 "Ignoring " name ".\n")
101 ; Read a macro-insn description
102 ; This is the main routine for analyzing macro-insns in the .cpu file.
103 ; ERRTXT is prepended to error messages to provide context.
104 ; ARG-LIST is an associative list of field name and field value.
105 ; -minsn-parse is invoked to create the `macro-insn' object.
107 (define (-minsn-read errtxt . arg-list)
108 (let (; Current macro-insn elements:
115 ; Loop over each element in ARG-LIST, recording what's found.
116 (let loop ((arg-list arg-list))
119 (let ((arg (car arg-list))
120 (elm-name (caar arg-list)))
122 ((name) (set! name (cadr arg)))
123 ((comment) (set! comment (cadr arg)))
124 ((attrs) (set! attrs (cdr arg)))
125 ((syntax) (set! syntax (cadr arg)))
126 ((expansions) (set! expansions (cdr arg)))
127 (else (parse-error errtxt "invalid macro-insn arg" arg)))
128 (loop (cdr arg-list)))))
129 ; Now that we've identified the elements, build the object.
130 (-minsn-parse errtxt name comment attrs syntax expansions)
134 ; Define a macro-insn object, name/value pair list version.
138 (if (eq? APPLICATION 'SIMULATOR)
139 #f ; don't waste time if simulator
140 (let ((m (apply -minsn-read (cons "define-minsn" arg-list))))
142 (current-minsn-add! m))
146 ; Define a macro-insn object, all arguments specified.
147 ; This only supports one expansion.
148 ; Use define-minsn for the general case (??? which is of course not implemented
151 (define (define-full-minsn name comment attrs syntax expansion)
152 (if (eq? APPLICATION 'SIMULATOR)
153 #f ; don't waste time if simulator
154 (let ((m (-minsn-parse "define-full-minsn" name comment
156 syntax (list expansion))))
158 (current-minsn-add! m))
162 ; Compute the ifield list for an alias macro-insn.
163 ; This involves making a copy of REAL-INSN's ifield list and assigning
164 ; known quantities to operands that have fixed values in the macro-insn.
166 (define (minsn-compute-iflds errtxt minsn-iflds real-insn)
167 (let* ((iflds (list-copy (insn-iflds real-insn)))
168 ; List of "free variables", i.e. operands.
169 (ifld-ops (find ifld-operand? iflds))
170 ; Names of fields in `ifld-ops'. As elements of minsn-iflds are
171 ; parsed the associated element in ifld-names is deleted. At the
172 ; end ifld-names must be empty. delq! can't delete the first
173 ; element in a list, so we insert a fencepost.
174 (ifld-names (cons #f (map obj:name ifld-ops))))
175 ;(logit 3 "Computing ifld list, operand field names: " ifld-names "\n")
176 ; For each macro-insn ifield expression, look it up in the real insn's
177 ; ifield list. If an operand without a prespecified value, leave
178 ; unchanged. If an operand or ifield with a value, assign the value to
180 (for-each (lambda (f)
181 (let* ((op-name (if (pair? f) (car f) f))
182 (op-obj (current-op-lookup op-name))
183 ; If `op-name' is an operand, use its ifield.
184 ; Otherwise `op-name' must be an ifield name.
186 (obj:name (hw-index:value (op:index op-obj)))
188 (ifld-pair (object-memq f-name iflds)))
189 ;(logit 3 "Processing ifield " f-name " ...\n")
191 (parse-error errtxt "unknown operand" f))
192 ; Ensure `f' is an operand.
193 (if (not (memq f-name ifld-names))
194 (parse-error errtxt "not an operand" f))
196 (set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
197 (delq! f-name ifld-names)))
199 (if (not (equal? ifld-names '(#f)))
200 (parse-error errtxt "incomplete operand list, missing: " (cdr ifld-names)))
204 ; Create an aliased real insn from an alias macro-insn.
206 (define (minsn-make-alias errtxt minsn)
207 (if (or (not (has-attr? minsn 'ALIAS))
208 ; Must emit exactly one real insn.
209 (not (eq? 'emit (caar (minsn-expansions minsn)))))
210 (parse-error errtxt "not an alias macro-insn" minsn))
212 (let* ((expn (car (minsn-expansions minsn)))
213 (alias-of (current-insn-lookup (cadr expn))))
216 (parse-error errtxt "unknown real insn in expansion" minsn))
218 (let ((i (make <insn>
223 (minsn-compute-iflds (string-append errtxt
224 ": " (obj:str-name minsn))
225 (cddr expn) alias-of)
226 #f ; ifield-assertion
230 ; FIXME: use same format entry as real insn,
231 ; build mask and test value at run time.
232 (insn-set-ifmt! i (ifmt-build i -1 #f (insn-iflds i))) ; (car (ifmt-analyze i #f))))
233 ;(insn-set-ifmt! i (insn-ifmt alias-of))
237 ; Called before a .cpu file is read in.
239 (define (minsn-init!)
240 (reader-add-command! 'define-minsn
242 Define a macro instruction, name/value pair list version.
244 nil 'arg-list define-minsn)
245 (reader-add-command! 'define-full-minsn
247 Define a macro instruction, all arguments specified.
249 nil '(name comment attrs syntax expansion)
255 ; Called after the .cpu file has been read in.
257 (define (minsn-finish!)