OSDN Git Service

* operand.scm (op-nub): Delete.
[pf3gnuchains/pf3gnuchains4x.git] / cgen / minsn.scm
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.
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               '(<source-ident>)
28               '(
29                 ; syntax of the macro
30                 syntax
31                 ; list of expansion expressions
32                 expansions
33                 )
34               nil)
35 )
36
37 (method-make-make! <macro-insn>
38                    '(location name comment attrs syntax expansions))
39
40 ; Accessor fns
41
42 (define minsn-syntax (elm-make-getter <macro-insn> 'syntax))
43 (define minsn-expansions (elm-make-getter <macro-insn> 'expansions))
44
45 ; Return a list of the machs that support MINSN.
46
47 (define (minsn-machs minsn)
48   nil
49 )
50
51 ; Return macro-instruction mnemonic.
52 ; This is computed from the syntax string.
53
54 (define minsn-mnemonic insn-mnemonic)
55
56 ; Return enum cgen_minsn_types value for MINSN.
57
58 (define (minsn-enum minsn)
59   (string-upcase (string-append "@ARCH@_MINSN_" (gen-sym minsn)))
60 )
61
62 ; Parse a macro-insn expansion description.
63 ; ??? At present we only support unconditional simple expansion.
64
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))
70   expn
71 )
72 \f
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).
78
79 (define (/minsn-parse context name comment attrs syntax expansions)
80   (logit 2 "Processing macro-insn " name " ...\n")
81
82   (if (not (list? expansions))
83       (parse-error context "invalid macro expansion list" expansions))
84
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")))
89
90     (if (keep-atlist? atlist-obj #f)
91
92         (let ((result (make <macro-insn>
93                         (context-location context)
94                         name
95                         (parse-comment context comment)
96                         atlist-obj
97                         (parse-syntax context syntax)
98                         (map (lambda (e) (/minsn-parse-expansion context e))
99                              expansions))))
100           result)
101
102         (begin
103           (logit 2 "Ignoring " name ".\n")
104           #f)))
105 )
106
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.
112
113 (define (/minsn-read context . arg-list)
114   (let (
115         (name nil)
116         (comment "")
117         (attrs nil)
118         (syntax "")
119         (expansions nil)
120         )
121
122     ; Loop over each element in ARG-LIST, recording what's found.
123     (let loop ((arg-list arg-list))
124       (if (null? arg-list)
125           nil
126           (let ((arg (car arg-list))
127                 (elm-name (caar arg-list)))
128             (case elm-name
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)))))
136
137     ; Now that we've identified the elements, build the object.
138     (/minsn-parse context name comment attrs syntax expansions))
139 )
140
141 ; Define a macro-insn object, name/value pair list version.
142
143 (define define-minsn
144   (lambda arg-list
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")
148                                           arg-list))))
149           (if m
150               (current-minsn-add! m))
151           m)))
152 )
153
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
157 ; yet :-).
158
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")
163                              name comment
164                              (cons 'ALIAS attrs)
165                              syntax (list expansion))))
166         (if m
167             (current-minsn-add! m))
168         m))
169 )
170 \f
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.
174
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
189     ; the ifield entry.
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.
195                        (f-name (if op-obj
196                                    (obj:name (hw-index:value (op:index op-obj)))
197                                    op-name))
198                        (ifld-pair (object-memq f-name iflds)))
199                   ;(logit 3 "Processing ifield " f-name " ...\n")
200                   (if (not ifld-pair)
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))
205                   (if (pair? f)
206                       (set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
207                   (delq! f-name ifld-names)))
208               minsn-iflds)
209     (if (not (equal? ifld-names '(#f)))
210         (parse-error context "incomplete operand list, missing: " (cdr ifld-names)))
211     iflds)
212 )
213
214 ; Create an aliased real insn from an alias macro-insn.
215
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))
221
222   (let* ((expn (car (minsn-expansions minsn)))
223          (alias-of (current-insn-lookup (cadr expn) (obj-isa-list minsn))))
224
225     (if (not alias-of)
226         (parse-error context "unknown real insn in expansion" minsn))
227
228     (let ((i (make <insn>
229                    (context-location context)
230                    (obj:name minsn)
231                    (obj:comment minsn)
232                    (obj-atlist minsn)
233                    (minsn-syntax minsn)
234                    (/minsn-compute-iflds (context-append context
235                                                          (string-append ": " (obj:str-name minsn)))
236                                          (cddr expn) alias-of)
237                    #f ; ifield-assertion
238                    #f ; semantics
239                    #f ; timing
240                    )))
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))
245       i))
246 )
247 \f
248 ; Called before a .cpu file is read in.
249
250 (define (minsn-init!)
251   (reader-add-command! 'define-minsn
252                        "\
253 Define a macro instruction, name/value pair list version.
254 "
255                        nil 'arg-list define-minsn)
256   (reader-add-command! 'define-full-minsn
257                        "\
258 Define a macro instruction, all arguments specified.
259 "
260                        nil '(name comment attrs syntax expansion)
261                        define-full-minsn)
262
263   *UNSPECIFIED*
264 )
265
266 ; Called after the .cpu file has been read in.
267
268 (define (minsn-finish!)
269   *UNSPECIFIED*
270 )