OSDN Git Service

2006-05-09 Dave Brolley <brolley@redhat.com>
[pf3gnuchains/pf3gnuchains4x.git] / cgen / minsn.scm
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.
5
6 ; Expansion:
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).
15
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.
20
21 ; ??? At present we only support macros that are aliases of one real insn.
22 \f
23 ; Object to describe a macro-insn.
24
25 (define <macro-insn>
26   (class-make '<macro-insn>
27               '(<ident>)
28               '(
29                 ; syntax of the macro
30                 syntax
31                 ; list of expansion expressions
32                 expansions
33                 )
34               nil)
35 )
36
37 ; Accessor fns
38
39 (define minsn-syntax (elm-make-getter <macro-insn> 'syntax))
40 (define minsn-expansions (elm-make-getter <macro-insn> 'expansions))
41
42 ; Return a list of the machs that support MINSN.
43
44 (define (minsn-machs minsn)
45   nil
46 )
47
48 ; Return macro-instruction mnemonic.
49 ; This is computed from the syntax string.
50
51 (define minsn-mnemonic insn-mnemonic)
52
53 ; Return enum cgen_minsn_types value for MINSN.
54
55 (define (minsn-enum minsn)
56   (string-upcase (string-append "@ARCH@_MINSN_" (gen-sym minsn)))
57 )
58
59 ; Parse a macro-insn expansion description.
60 ; ??? At present we only support unconditional simple expansion.
61
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))
67   expn
68 )
69 \f
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).
75
76 (define (-minsn-parse errtxt name comment attrs syntax expansions)
77   (logit 2 "Processing macro-insn " name " ...\n")
78
79   (if (not (list? expansions))
80       (parse-error errtxt "invalid macro expansion list" expansions))
81
82   (let ((name (parse-name name errtxt))
83         (atlist-obj (atlist-parse attrs "cgen_minsn" errtxt)))
84
85     (if (keep-atlist? atlist-obj #f)
86
87         (let ((result (make <macro-insn>
88                         name
89                         (parse-comment comment errtxt)
90                         atlist-obj
91                         (parse-syntax syntax errtxt)
92                         (map (lambda (e) (-minsn-parse-expansion errtxt e))
93                              expansions))))
94           result)
95
96         (begin
97           (logit 2 "Ignoring " name ".\n")
98           #f)))
99 )
100
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.
106
107 (define (-minsn-read errtxt . arg-list)
108   (let (; Current macro-insn elements:
109         (name nil)
110         (comment "")
111         (attrs nil)
112         (syntax "")
113         (expansions nil)
114         )
115     ; Loop over each element in ARG-LIST, recording what's found.
116     (let loop ((arg-list arg-list))
117       (if (null? arg-list)
118           nil
119           (let ((arg (car arg-list))
120                 (elm-name (caar arg-list)))
121             (case elm-name
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)
131     )
132 )
133
134 ; Define a macro-insn object, name/value pair list version.
135
136 (define define-minsn
137   (lambda arg-list
138     (if (eq? APPLICATION 'SIMULATOR)
139         #f ; don't waste time if simulator
140         (let ((m (apply -minsn-read (cons "define-minsn" arg-list))))
141           (if m
142               (current-minsn-add! m))
143           m)))
144 )
145
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
149 ; yet :-).
150
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
155                              (cons 'ALIAS attrs)
156                              syntax (list expansion))))
157         (if m
158             (current-minsn-add! m))
159         m))
160 )
161 \f
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.
165
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
179     ; the ifield entry.
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.
185                        (f-name (if op-obj
186                                    (obj:name (hw-index:value (op:index op-obj)))
187                                    op-name))
188                        (ifld-pair (object-memq f-name iflds)))
189                   ;(logit 3 "Processing ifield " f-name " ...\n")
190                   (if (not ifld-pair)
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))
195                   (if (pair? f)
196                       (set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
197                   (delq! f-name ifld-names)))
198               minsn-iflds)
199     (if (not (equal? ifld-names '(#f)))
200         (parse-error errtxt "incomplete operand list, missing: " (cdr ifld-names)))
201     iflds)
202 )
203
204 ; Create an aliased real insn from an alias macro-insn.
205
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))
211
212   (let* ((expn (car (minsn-expansions minsn)))
213          (alias-of (current-insn-lookup (cadr expn))))
214
215     (if (not alias-of)
216         (parse-error errtxt "unknown real insn in expansion" minsn))
217
218     (let ((i (make <insn>
219                    (obj:name minsn)
220                    (obj:comment minsn)
221                    (obj-atlist minsn)
222                    (minsn-syntax minsn)
223                    (minsn-compute-iflds (string-append errtxt
224                                                        ": " (obj:str-name minsn))
225                                         (cddr expn) alias-of)
226                    #f ; ifield-assertion
227                    #f ; semantics
228                    #f ; timing
229                    )))
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))
234       i))
235 )
236 \f
237 ; Called before a .cpu file is read in.
238
239 (define (minsn-init!)
240   (reader-add-command! 'define-minsn
241                        "\
242 Define a macro instruction, name/value pair list version.
243 "
244                        nil 'arg-list define-minsn)
245   (reader-add-command! 'define-full-minsn
246                        "\
247 Define a macro instruction, all arguments specified.
248 "
249                        nil '(name comment attrs syntax expansion)
250                        define-full-minsn)
251
252   *UNSPECIFIED*
253 )
254
255 ; Called after the .cpu file has been read in.
256
257 (define (minsn-finish!)
258   *UNSPECIFIED*
259 )