-
Notifications
You must be signed in to change notification settings - Fork 0
/
minsn.scm
270 lines (227 loc) · 8.5 KB
/
minsn.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
; Macro instruction definitions.
; Copyright (C) 2000, 2009 Red Hat, Inc.
; This file is part of CGEN.
; See file COPYING.CGEN for details.
; Expansion:
; If the macro expands to a string, arguments in the input string
; are refered to with %N. Multiple insns are separated with '\n'.
; String expansion is a special case of the normal form which is a Scheme
; expression that controls the expansion. The Scheme expression will be able
; to refer to the current assembly state to decide how to perform the
; expansion. Special expression `emit' is used to call the assembler emitter
; for a particular insn. Special expression `expand' is used to return a
; string to be reparsed (which is special cased).
; Parse a list of macro-instruction expansion descriptions.
; This is the main routine for building an minsn-expansion object from a
; description in the .cpu file.
; All arguments are in raw (non-evaluated) form.
; ??? At present we only support macros that are aliases of one real insn.
; Object to describe a macro-insn.
(define <macro-insn>
(class-make '<macro-insn>
'(<source-ident>)
'(
; syntax of the macro
syntax
; list of expansion expressions
expansions
)
nil)
)
(method-make-make! <macro-insn>
'(location name comment attrs syntax expansions))
; Accessor fns
(define minsn-syntax (elm-make-getter <macro-insn> 'syntax))
(define minsn-expansions (elm-make-getter <macro-insn> 'expansions))
; Return a list of the machs that support MINSN.
(define (minsn-machs minsn)
nil
)
; Return macro-instruction mnemonic.
; This is computed from the syntax string.
(define minsn-mnemonic insn-mnemonic)
; Return enum cgen_minsn_types value for MINSN.
(define (minsn-enum minsn)
(string-upcase (string-append "@ARCH@_MINSN_" (gen-sym minsn)))
)
; Parse a macro-insn expansion description.
; ??? At present we only support unconditional simple expansion.
(define (/minsn-parse-expansion context expn)
(if (not (form? expn))
(parse-error context "invalid macro expansion" expn))
(if (not (eq? 'emit (car expn)))
(parse-error context "invalid macro expansion, must be `(emit ...)'" expn))
expn
)
; Parse a macro-instruction description.
; This is the main routine for building a macro-insn object from a
; description in the .cpu file.
; All arguments are in raw (non-evaluated) form.
; The result is the parsed object or #f if object isn't for selected mach(s).
(define (/minsn-parse context name comment attrs syntax expansions)
(logit 2 "Processing macro-insn " name " ...\n")
(if (not (list? expansions))
(parse-error context "invalid macro expansion list" expansions))
;; Pick out name first to augment the error context.
(let* ((name (parse-name context name))
(context (context-append-name context name))
(atlist-obj (atlist-parse context attrs "cgen_minsn")))
(if (keep-atlist? atlist-obj #f)
(let ((result (make <macro-insn>
(context-location context)
name
(parse-comment context comment)
atlist-obj
(parse-syntax context syntax)
(map (lambda (e) (/minsn-parse-expansion context e))
expansions))))
result)
(begin
(logit 2 "Ignoring " name ".\n")
#f)))
)
; Read a macro-insn description
; This is the main routine for analyzing macro-insns in the .cpu file.
; CONTEXT is a <context> object for error messages.
; ARG-LIST is an associative list of field name and field value.
; /minsn-parse is invoked to create the `macro-insn' object.
(define (/minsn-read context . arg-list)
(let (
(name nil)
(comment "")
(attrs nil)
(syntax "")
(expansions nil)
)
; Loop over each element in ARG-LIST, recording what's found.
(let loop ((arg-list arg-list))
(if (null? arg-list)
nil
(let ((arg (car arg-list))
(elm-name (caar arg-list)))
(case elm-name
((name) (set! name (cadr arg)))
((comment) (set! comment (cadr arg)))
((attrs) (set! attrs (cdr arg)))
((syntax) (set! syntax (cadr arg)))
((expansions) (set! expansions (cdr arg)))
(else (parse-error context "invalid macro-insn arg" arg)))
(loop (cdr arg-list)))))
; Now that we've identified the elements, build the object.
(/minsn-parse context name comment attrs syntax expansions))
)
; Define a macro-insn object, name/value pair list version.
(define define-minsn
(lambda arg-list
(if (eq? APPLICATION 'SIMULATOR)
#f ; don't waste time if simulator
(let ((m (apply /minsn-read (cons (make-current-context "define-minsn")
arg-list))))
(if m
(current-minsn-add! m))
m)))
)
; Define a macro-insn object, all arguments specified.
; This only supports one expansion.
; Use define-minsn for the general case (??? which is of course not implemented
; yet :-).
(define (define-full-minsn name comment attrs syntax expansion)
(if (eq? APPLICATION 'SIMULATOR)
#f ; don't waste time if simulator
(let ((m (/minsn-parse (make-current-context "define-full-minsn")
name comment
(cons 'ALIAS attrs)
syntax (list expansion))))
(if m
(current-minsn-add! m))
m))
)
; Compute the ifield list for an alias macro-insn.
; This involves making a copy of REAL-INSN's ifield list and assigning
; known quantities to operands that have fixed values in the macro-insn.
(define (/minsn-compute-iflds context minsn-iflds real-insn)
(let* ((iflds (list-copy (insn-iflds real-insn)))
; List of "free variables", i.e. operands.
(ifld-ops (find ifld-operand? iflds))
; Names of fields in `ifld-ops'. As elements of minsn-iflds are
; parsed the associated element in ifld-names is deleted. At the
; end ifld-names must be empty. delq! can't delete the first
; element in a list, so we insert a fencepost.
(ifld-names (cons #f (map obj:name ifld-ops)))
(isa-name-list (obj-isa-list real-insn)))
;(logit 3 "Computing ifld list, operand field names: " ifld-names "\n")
; For each macro-insn ifield expression, look it up in the real insn's
; ifield list. If an operand without a prespecified value, leave
; unchanged. If an operand or ifield with a value, assign the value to
; the ifield entry.
(for-each (lambda (f)
(let* ((op-name (if (pair? f) (car f) f))
(op-obj (current-op-lookup op-name isa-name-list))
; If `op-name' is an operand, use its ifield.
; Otherwise `op-name' must be an ifield name.
(f-name (if op-obj
(obj:name (hw-index:value (op:index op-obj)))
op-name))
(ifld-pair (object-memq f-name iflds)))
;(logit 3 "Processing ifield " f-name " ...\n")
(if (not ifld-pair)
(parse-error context "unknown operand" f))
; Ensure `f' is an operand.
(if (not (memq f-name ifld-names))
(parse-error context "not an operand" f))
(if (pair? f)
(set-car! ifld-pair (ifld-new-value (car ifld-pair) (cadr f))))
(delq! f-name ifld-names)))
minsn-iflds)
(if (not (equal? ifld-names '(#f)))
(parse-error context "incomplete operand list, missing: " (cdr ifld-names)))
iflds)
)
; Create an aliased real insn from an alias macro-insn.
(define (minsn-make-alias context minsn)
(if (or (not (has-attr? minsn 'ALIAS))
; Must emit exactly one real insn.
(not (eq? 'emit (caar (minsn-expansions minsn)))))
(parse-error context "not an alias macro-insn" minsn))
(let* ((expn (car (minsn-expansions minsn)))
(alias-of (current-insn-lookup (cadr expn) (obj-isa-list minsn))))
(if (not alias-of)
(parse-error context "unknown real insn in expansion" minsn))
(let ((i (make <insn>
(context-location context)
(obj:name minsn)
(obj:comment minsn)
(obj-atlist minsn)
(minsn-syntax minsn)
(/minsn-compute-iflds (context-append context
(string-append ": " (obj:str-name minsn)))
(cddr expn) alias-of)
#f ; ifield-assertion
#f ; semantics
#f ; timing
)))
; FIXME: use same format entry as real insn,
; build mask and test value at run time.
(insn-set-ifmt! i (ifmt-build i -1 #f (insn-iflds i))) ; (car (ifmt-analyze i #f))))
;(insn-set-ifmt! i (insn-ifmt alias-of))
i))
)
; Called before a .cpu file is read in.
(define (minsn-init!)
(reader-add-command! 'define-minsn
"\
Define a macro instruction, name/value pair list version.
"
nil 'arg-list define-minsn)
(reader-add-command! 'define-full-minsn
"\
Define a macro instruction, all arguments specified.
"
nil '(name comment attrs syntax expansion)
define-full-minsn)
*UNSPECIFIED*
)
; Called after the .cpu file has been read in.
(define (minsn-finish!)
*UNSPECIFIED*
)