2 ; Copyright (C) 2000, 2001, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4 ; See file COPYING.CGEN for details.
6 ; The name for the description language has been changed a couple of times.
7 ; RTL isn't my favorite because of perceived confusion with GCC
8 ; (and perceived misinterpretation of intentions!).
9 ; On the other hand my other choices were taken (and believed to be
12 ; RTL functions are described by class <rtx-func>.
13 ; The complete list of rtl functions is defined in doc/rtl.texi.
15 ; Conventions used in this file:
16 ; - procs that perform the basic rtl or semantic expression manipulation that
17 ; is for public use shall be prefixed with "s-" or "rtl-" or "rtx-"
18 ; - no other procs shall be so prefixed
19 ; - rtl globals and other rtx-func object support shall be prefixed with
21 ; - no other procs shall be so prefixed
23 ; Class for defining rtx nodes.
25 ; FIXME: Add new members that are lambda's to perform the argument checking
26 ; specified by `arg-types' and `arg-modes'. This will save a lookup during
27 ; traversing. It will also allow custom versions for oddballs (e.g. for
28 ; `member' we want to verify the 2nd arg is a `number-list' rtx).
32 (class-make '<rtx-func> nil
34 ; name as it appears in RTL
40 ; types of each argument, as symbols
41 ; This is #f for macros.
43 ; OPTIONS - optional list of :-prefixed options.
45 ; INTMODE - any integer mode
46 ; FLOATMODE - any floating point mode
47 ; NUMMODE - any numeric mode
48 ; EXPLNUMMODE - explicit numeric mode, can't be DFLT or VOID
49 ; NONVOIDMODE - can't be `VOID'
50 ; VOIDMODE - must be `VOID'
51 ; DFLTMODE - must be `DFLT', used when any mode is inappropriate
53 ; SETRTX - any rtx allowed to be `set'
54 ; TESTRTX - the test of an `if'
55 ; CONDRTX - a cond expression ((test) rtx ... rtx)
56 ; CASERTX - a case expression ((symbol .. symbol) rtx ... rtx)
57 ; LOCALS - the locals list of a sequence
58 ; ENV - environment stack
59 ; ATTRS - attribute list
60 ; SYMBOL - operand must be a symbol
61 ; STRING - operand must be a string
62 ; NUMBER - operand must be a number
63 ; SYMORNUM - operand must be a symbol or number
64 ; OBJECT - operand is an object
67 ; required mode of each argument
68 ; This is #f for macros.
69 ; Possible values include any mode name and:
72 ; OP0 - mode is specified in operand 0
73 ; unless it is DFLT in which case use the default mode
75 ; MATCH1 - must match mode of operand 1
76 ; which will have OP0 for its mode spec
77 ; MATCH2 - must match mode of operand 2
78 ; which will have OP0 for its mode spec
79 ; <MODE-NAME> - must match specified mode
83 ; This is #f for macros.
84 ; ARG - operand, local, const
86 ; UNARY - not, inv, etc.
87 ; BINARY - add, sub, etc.
88 ; TRINARY - addc, subc, etc.
91 ; SEQUENCE - sequence, parallel
93 ; MISC - everything else
96 ; A symbol indicating the flavour of rtx node this is.
97 ; function - normal function
98 ; syntax - don't pre-eval arguments
99 ; operand - result is an operand
100 ; macro - converts one rtx expression to another
101 ; The word "style" was chosen to be sufficiently different
102 ; from "type", "kind", and "class".
105 ; A function to perform the rtx.
108 ; Ordinal number of rtx. Used to index into tables.
116 (define (rtx-func? x) (class-instance? <rtx-func> x))
120 (define-getters <rtx-func> rtx
121 (name args arg-types arg-modes class style evaluator num)
124 (define (rtx-style-syntax? rtx) (eq? (rtx-style rtx) 'syntax))
126 ; Add standard `get-name' method since this isn't a subclass of <ident>.
128 (method-make! <rtx-func> 'get-name (lambda (self) (elm-get self 'name)))
130 ; List of mode types for arg-types.
132 (define /rtx-valid-mode-types
134 ANYMODE INTMODE FLOATMODE NUMMODE EXPLNUMMODE NONVOIDMODE VOIDMODE DFLTMODE
138 ; List of valid values for arg-types, not including mode names.
140 (define /rtx-valid-types
143 /rtx-valid-mode-types
144 '(RTX SETRTX TESTRTX CONDRTX CASERTX)
145 '(LOCALS ENV ATTRS SYMBOL STRING NUMBER SYMORNUM OBJECT)
149 ; List of valid mode matchers, excluding mode names.
151 (define /rtx-valid-matches
152 '(ANY NA OP0 MATCH1 MATCH2)
155 ; List of all defined rtx names. This can be map'd over without having
156 ; to know the innards of /rtx-func-table (which is a hash table).
158 (define /rtx-name-list nil)
159 (define (rtx-name-list) /rtx-name-list)
161 ; Table of rtx function objects.
162 ; This is set in rtl-init!.
164 (define /rtx-func-table nil)
166 ; Look up the <rtx-func> object for RTX-KIND.
167 ; Returns the object or #f if not found.
168 ; RTX-KIND may already be an <rtx-func> object. FIXME: delete?
170 (define (rtx-lookup rtx-kind)
171 (cond ((symbol? rtx-kind)
172 (hashq-ref /rtx-func-table rtx-kind))
173 ((rtx-func? rtx-kind)
178 ; Table of rtx macro objects.
179 ; This is set in rtl-init!.
181 (define /rtx-macro-table nil)
183 ; Table of operands, modes, and other non-functional aspects of RTL.
184 ; This is defined in rtl-finish!, after all operands have been read in.
186 (define /rtx-operand-table nil)
188 ; Number of next rtx to be defined.
190 (define /rtx-num-next #f)
192 ; Return the number of rtx's.
194 (define (rtx-max-num)
200 ; Add an entry to the rtx function table.
201 ; NAME-ARGS is a list of the operation name and arguments.
202 ; The mode of the result must be the first element in `args' (if there are
204 ; ARG-TYPES is a list of argument types (/rtx-valid-types).
205 ; ARG-MODES is a list of mode matchers (/rtx-valid-matches).
206 ; CLASS is the class of the rtx to be created.
207 ; ACTION is a list of Scheme expressions to perform the operation.
209 ; ??? Note that we can support variables. Not sure it should be done.
211 (define (def-rtx-node name-args arg-types arg-modes class action)
212 (let ((name (car name-args))
213 (args (cdr name-args)))
214 (let ((rtx (make <rtx-func> name args
219 (eval1 (list 'lambda (cons '*estate* args) action))
222 ; Add it to the table of rtx handlers.
223 (hashq-set! /rtx-func-table name rtx)
224 (set! /rtx-num-next (+ /rtx-num-next 1))
225 (set! /rtx-name-list (cons name /rtx-name-list))
229 (define define-rtx-node
230 ; Written this way so Hobbit can handle it.
231 (defmacro:syntax-transformer (lambda arg-list
232 (apply def-rtx-node arg-list)
236 ; Same as define-rtx-node but don't pre-evaluate the arguments.
237 ; Remember that `mode' must be the first argument.
239 (define (def-rtx-syntax-node name-args arg-types arg-modes class action)
240 (let ((name (car name-args))
241 (args (cdr name-args)))
242 (let ((rtx (make <rtx-func> name args
247 (eval1 (list 'lambda (cons '*estate* args) action))
250 ; Add it to the table of rtx handlers.
251 (hashq-set! /rtx-func-table name rtx)
252 (set! /rtx-num-next (+ /rtx-num-next 1))
253 (set! /rtx-name-list (cons name /rtx-name-list))
257 (define define-rtx-syntax-node
258 ; Written this way so Hobbit can handle it.
259 (defmacro:syntax-transformer (lambda arg-list
260 (apply def-rtx-syntax-node arg-list)
264 ; Same as define-rtx-node but return an operand (usually an <operand> object).
265 ; ??? `mode' must be the first argument?
267 (define (def-rtx-operand-node name-args arg-types arg-modes class action)
268 ; Operand nodes must specify an action.
270 (let ((name (car name-args))
271 (args (cdr name-args)))
272 (let ((rtx (make <rtx-func> name args
276 (eval1 (list 'lambda (cons '*estate* args) action))
278 ; Add it to the table of rtx handlers.
279 (hashq-set! /rtx-func-table name rtx)
280 (set! /rtx-num-next (+ /rtx-num-next 1))
281 (set! /rtx-name-list (cons name /rtx-name-list))
285 (define define-rtx-operand-node
286 ; Written this way so Hobbit can handle it.
287 (defmacro:syntax-transformer (lambda arg-list
288 (apply def-rtx-operand-node arg-list)
292 ; Convert one rtx expression into another.
293 ; NAME-ARGS is a list of the operation name and arguments.
294 ; ACTION is a list of Scheme expressions to perform the operation.
295 ; The result of ACTION must be another rtx expression (a list).
297 (define (def-rtx-macro-node name-args action)
298 ; macro nodes must specify an action
300 (let ((name (car name-args))
301 (args (cdr name-args)))
302 (let ((rtx (make <rtx-func> name args #f #f
305 (eval1 (list 'lambda args action))
307 ; Add it to the table of rtx macros.
308 (hashq-set! /rtx-macro-table name rtx)
309 (set! /rtx-num-next (+ /rtx-num-next 1))
310 (set! /rtx-name-list (cons name /rtx-name-list))
314 (define define-rtx-macro-node
315 ; Written this way so Hobbit can handle it.
316 (defmacro:syntax-transformer (lambda arg-list
317 (apply def-rtx-macro-node arg-list)
321 ; RTL macro expansion.
322 ; RTL macros are different than pmacros. The difference is that the expansion
323 ; happens internally, RTL macros are part of the language.
325 ; Lookup MACRO-NAME and return its <rtx-func> object or #f if not found.
327 (define (/rtx-macro-lookup macro-name)
328 (hashq-ref /rtx-macro-table macro-name)
331 ; Lookup (car exp) and return the macro's lambda if it is one or #f.
333 (define (/rtx-macro-check exp fn-getter)
334 (let ((macro (hashq-ref /rtx-macro-table (car exp))))
342 (define (/rtx-macro-expand-list exp fn-getter)
343 (let ((macro (/rtx-macro-check exp fn-getter)))
345 (apply macro (map (lambda (x) (/rtx-macro-expand x fn-getter))
347 (map (lambda (x) (/rtx-macro-expand x fn-getter))
351 ; Main entry point to expand a macro invocation.
353 (define (/rtx-macro-expand exp fn-getter)
354 (if (pair? exp) ; pair? -> cheap (and (not (null? exp)) (list? exp))
355 (let ((result (/rtx-macro-expand-list exp fn-getter)))
356 ; If the result is a new macro invocation, recurse.
358 (let ((macro (/rtx-macro-check result fn-getter)))
360 (/rtx-macro-expand (apply macro (cdr result)) fn-getter)
366 ; Publically accessible version.
368 (define rtx-macro-expand /rtx-macro-expand)
372 ; Get implied mode of X, either an operand expression, sequence temp, or
373 ; a hardware reference expression.
374 ; The result is the name of the mode.
376 (define (rtx-lvalue-mode-name estate x)
379 ; ((operand) (obj:name (op:mode (current-op-lookup (cadr x)))))
380 ((xop) (obj:name (send (rtx-xop-obj x) 'get-mode)))
382 ; (if (eq? (rtx-opspec-mode x) 'VOID)
383 ; (rtx-lvalue-mode-name estate (rtx-opspec-hw-ref x))
384 ; (rtx-opspec-mode x)))
385 ; ((reg mem) (cadr x))
386 ((local) ;; (local options mode name)
387 (let* ((name (cadddr x))
388 (temp (rtx-temp-lookup (estate-env estate) name)))
390 (estate-error estate "unknown local" name))
391 (obj:name (rtx-temp-mode temp))))
394 "rtx-lvalue-mode-name: not an operand or hardware reference:"
398 ; Lookup the mode to use for semantic operations (unsigned modes aren't
399 ; allowed since we don't have ANDUSI, etc.).
400 ; MODE is a <mode> object.
401 ; ??? I have actually implemented both ways (full use of unsigned modes
402 ; and mostly hidden use of unsigned modes). Neither makes me real
403 ; comfortable, though I liked bringing unsigned modes out into the open
404 ; even if it doubled the number of semantic operations.
406 (define (rtx-sem-mode mode) (or (mode:sem-mode mode) mode))
408 ; MODE is a <mode> object.
410 (define (rtx-lazy-sem-mode mode) (rtx-sem-mode mode))
412 ; Return the mode of object OBJ.
414 (define (rtx-obj-mode obj) (send obj 'get-mode))
416 ; Return a boolean indicating of modes M1,M2 are compatible.
417 ; M1,M2 are <mode> objects.
419 (define (rtx-mode-compatible? m1 m2)
420 (let ((mode1 (rtx-lazy-sem-mode m1))
421 (mode2 (rtx-lazy-sem-mode m2)))
422 ;(eq? (obj:name mode1) (obj:name mode2)))
423 ; ??? This is more permissive than is perhaps proper.
424 (mode-compatible? 'sameclass mode1 mode2))
427 ; Environments (sequences with local variables).
429 ; Temporaries are created within a sequence.
430 ; MODE is a <mode> object.
431 ; e.g. (sequence ((WI tmp)) (set tmp reg0) ...)
432 ; ??? Perhaps what we want here is `let' but for now I prefer `sequence'.
433 ; This isn't exactly `let' either as no initial value is specified.
434 ; Environments are also used to specify incoming values from the top level.
436 (define <rtx-temp> (class-make '<rtx-temp> nil '(name mode value) nil))
438 ;(define cx-temp:name (elm-make-getter <c-expr-temp> 'name))
439 ;(define cx-temp:mode (elm-make-getter <c-expr-temp> 'mode))
440 ;(define cx-temp:value (elm-make-getter <c-expr-temp> 'value))
442 (define-getters <rtx-temp> rtx-temp (name mode value))
446 (lambda (self name mode value)
447 (assert (mode? mode))
448 (elm-set! self 'name name)
449 (elm-set! self 'mode mode)
450 (elm-set! self 'value (if value value (gen-temp name)))
454 (define (gen-temp name)
455 ; ??? calls to gen-c-symbol don't belong here
456 (string-append "tmp_" (gen-c-symbol name))
459 ; Return a boolean indicating if X is an <rtx-temp>.
461 (define (rtx-temp? x) (class-instance? <rtx-temp> x))
463 ; Respond to 'get-mode messages.
465 (method-make! <rtx-temp> 'get-mode (lambda (self) (elm-get self 'mode)))
467 ; Respond to 'get-name messages.
469 (method-make! <rtx-temp> 'get-name (lambda (self) (elm-get self 'name)))
471 ; An environment is a list of <rtx-temp> objects.
472 ; An environment stack is a list of environments.
474 (define (rtx-env-stack-empty? env-stack) (null? env-stack))
475 (define (rtx-env-stack-head env-stack) (car env-stack))
476 (define (rtx-env-var-list env) env)
477 (define (rtx-env-empty-stack) nil)
478 (define (rtx-env-init-stack1 vars-alist)
479 (if (null? vars-alist)
481 (cons (rtx-env-make vars-alist) nil))
483 (define (rtx-env-empty? env) (null? env))
485 ; Create an initial environment.
486 ; VAR-LIST is a list of (name <mode>-or-mode-name value) elements.
488 (define (rtx-env-make var-list)
489 ; Convert VAR-LIST to an associative list of <rtx-temp> objects.
490 (map (lambda (var-spec)
494 (mode-maybe-lookup (cadr var-spec))
499 ; Create an initial environment with local variables.
500 ; VAR-LIST is a list of (mode-name name) elements, i.e. the locals argument to
501 ; `sequence' or equivalent thereof.
503 (define (rtx-env-make-locals var-list)
504 ; Convert VAR-LIST to an associative list of <rtx-temp> objects.
505 (map (lambda (var-spec)
506 (cons (cadr var-spec)
508 (cadr var-spec) (mode:lookup (car var-spec)) #f)))
512 ; Return the symbol name of the limit variable of `do-count'
513 ; given iteration-variable ITER-VAR.
514 ; ??? We don't publish that this variable is available to use, but we could.
516 (define (rtx-make-iteration-limit-var iter-var)
517 (symbol-append iter-var '-limit)
520 ; Create an environment with the iteration local variables of `do-count'.
522 (define (rtx-env-make-iteration-locals iter-var)
523 (rtx-env-make-locals (list (list 'INT iter-var)
524 (list 'INT (rtx-make-iteration-limit-var iter-var))))
527 ; Push environment ENV onto the front of environment stack ENV-STACK,
528 ; returning a new object. ENV-STACK is not modified.
530 (define (rtx-env-push env-stack env)
534 ; Lookup variable NAME in environment ENV.
535 ; The result is the <rtx-temp> object.
536 ; ??? Should environments only have rtx-temps?
538 (define (rtx-temp-lookup env name)
539 ;(display "looking up:") (display name) (newline)
540 (let loop ((stack (rtx-env-var-list env)))
543 (let ((temp (assq-ref (car stack) name)))
546 (loop (cdr stack))))))
549 ; Create a "closure" of EXPR using the current temp stack.
551 (define (/rtx-closure-make estate expr)
552 (rtx-make 'closure expr (estate-env estate))
555 (define (rtx-env-dump env)
557 (if (rtx-env-stack-empty? stack)
558 (display "rtx-env stack (empty):\n")
559 (let loop ((stack stack) (level 0))
563 (display "rtx-env stack, level ")
566 (for-each (lambda (var)
568 ;(display (obj:name (rtx-temp-mode (cdr var))))
570 (display (rtx-temp-name (cdr var)))
573 (loop (cdr stack) (+ level 1)))))))
576 ; Build, test, and analyze various kinds of rtx's.
577 ; ??? A lot of this could be machine generated except that I don't yet need
580 (define (rtx-make kind . args)
581 (cons kind (/rtx-munge-mode&options args))
584 (define rtx-name car)
585 (define (rtx-kind? kind rtx) (eq? kind (rtx-name rtx)))
587 (define (rtx-make-const mode value) (rtx-make 'const mode value))
588 (define (rtx-make-enum mode value) (rtx-make 'enum mode value))
590 (define (rtx-constant? rtx) (memq (rtx-name rtx) '(const enum)))
592 ; Return value of constant RTX (either const or enum).
593 (define (rtx-constant-value rtx)
595 ((const) (rtx-const-value rtx))
596 ((enum) (enum-lookup-val (rtx-enum-value rtx)))
597 (else (error "rtx-constant-value: not const or enum" rtx)))
600 (define rtx-options cadr)
601 (define rtx-mode caddr)
602 (define rtx-args cdddr)
603 (define rtx-arg1 cadddr)
604 (define (rtx-arg2 rtx) (car (cddddr rtx)))
606 (define rtx-const-value rtx-arg1)
607 (define rtx-enum-value rtx-arg1)
609 (define rtx-reg-name rtx-arg1)
611 ; Return register number or #f if absent.
612 ; (reg options mode hw-name [regno [selector]])
613 (define (rtx-reg-number rtx) (list-maybe-ref rtx 4))
615 ; Return register selector or #f if absent.
616 (define (rtx-reg-selector rtx) (list-maybe-ref rtx 5))
618 ; Return both register number and selector.
619 (define rtx-reg-index-sel cddddr)
621 ; Return memory address.
622 (define rtx-mem-addr rtx-arg1)
624 ; Return memory selector or #f if absent.
625 (define (rtx-mem-sel mem) (list-maybe-ref mem 4))
627 ; Return both memory address and selector.
628 (define rtx-mem-index-sel cdddr)
630 ; Return MEM with new address NEW-ADDR.
631 ; ??? Complicate as necessary.
632 (define (rtx-change-address mem new-addr)
640 ; Return argument to `symbol' rtx.
641 (define rtx-symbol-name rtx-arg1)
643 (define (rtx-make-ifield ifield-name) (rtx-make 'ifield ifield-name))
644 (define (rtx-ifield? rtx) (eq? 'ifield (rtx-name rtx)))
645 (define (rtx-ifield-name rtx)
646 (let ((ifield (rtx-arg1 rtx)))
651 (define (rtx-ifield-obj rtx)
652 (let ((ifield (rtx-arg1 rtx)))
654 (current-ifield-lookup ifield)
658 (define (rtx-make-operand op-name) (rtx-make 'operand op-name))
659 (define (rtx-operand? rtx) (eq? 'operand (rtx-name rtx)))
660 (define (rtx-operand-name rtx)
661 (let ((operand (rtx-arg1 rtx)))
662 (if (symbol? operand)
666 (define (rtx-operand-obj rtx)
667 (let ((operand (rtx-arg1 rtx)))
668 (if (symbol? operand)
669 (current-op-lookup operand)
673 (define (rtx-make-local local-name) (rtx-make 'local local-name))
674 (define (rtx-local? rtx) (eq? 'local (rtx-name rtx)))
675 (define (rtx-local-name rtx)
676 (let ((local (rtx-arg1 rtx)))
681 (define (rtx-local-obj rtx)
682 (let ((local (rtx-arg1 rtx)))
684 (error "can't use rtx-local-obj on local name")
688 (define rtx-xop-obj rtx-arg1)
690 ;(define (rtx-opspec? rtx) (eq? 'opspec (rtx-name rtx)))
691 ;(define (rtx-opspec-mode rtx) (rtx-mode rtx))
692 ;(define (rtx-opspec-hw-ref rtx) (list-ref rtx 5))
693 ;(define (rtx-opspec-set-op-num! rtx num) (set-car! (cddddr rtx) num))
695 (define rtx-index-of-value rtx-arg1)
697 (define (rtx-make-set dest src) (rtx-make 'set dest src))
698 (define rtx-set-dest rtx-arg1)
699 (define rtx-set-src rtx-arg2)
700 (define (rtx-single-set? rtx) (eq? (car rtx) 'set))
702 (define rtx-alu-op-mode rtx-mode)
703 (define (rtx-alu-op-arg rtx n) (list-ref rtx (+ n 3)))
705 (define (rtx-boolif-op-arg rtx n) (list-ref rtx (+ n 3)))
707 (define rtx-cmp-op-mode rtx-mode)
708 (define (rtx-cmp-op-arg rtx n) (list-ref rtx (+ n 3)))
710 (define rtx-number-list-values cdddr)
712 (define rtx-member-value rtx-arg1)
713 (define (rtx-member-set rtx) (list-ref rtx 4))
715 (define rtx-if-mode rtx-mode)
716 (define (rtx-if-test rtx) (rtx-arg1 rtx))
717 (define (rtx-if-then rtx) (list-ref rtx 4))
718 ; If `else' clause is missing the result is #f.
719 (define (rtx-if-else rtx) (list-maybe-ref rtx 5))
721 (define (rtx-eq-attr-owner rtx) (list-ref rtx 3))
722 (define (rtx-eq-attr-attr rtx) (list-ref rtx 4))
723 (define (rtx-eq-attr-value rtx) (list-ref rtx 5))
725 (define (rtx-sequence-locals rtx) (cadddr rtx))
726 (define (rtx-sequence-exprs rtx) (cddddr rtx))
728 ; Same as rtx-sequence-locals except return in assq'able form.
729 ; ??? Sometimes I should it should have been (sequence ((name MODE)) ...)
730 ; instead of (sequence ((MODE name)) ...) from the beginning, sigh.
732 (define (rtx-sequence-assq-locals rtx)
733 (let ((locals (rtx-sequence-locals rtx)))
735 (list (cadr local) (car local)))
739 ; Return a semi-pretty string describing RTX.
740 ; This is used by hw to include the index in the element's name.
742 (define (rtx-pretty-name rtx)
745 ((const) (number->string (rtx-const-value rtx)))
746 ((operand) (symbol->string (obj:name (rtx-operand-obj rtx))))
747 ((local) (symbol->string (rtx-local-name rtx)))
748 ((xop) (symbol->string (obj:name (rtx-xop-obj rtx))))
750 (if (null? (cdr rtx))
751 (rtx-pretty-name (car rtx))
752 (apply stringsym-append
753 (cons (rtx-pretty-name (car rtx))
755 (string-append "-" (rtx-pretty-name elm)))
760 ; Various rtx utilities.
762 ; Dump an rtx expression.
764 (define (rtx-dump rtx)
765 (cond ((list? rtx) (map rtx-dump rtx))
766 ((object? rtx) (string/symbol-append "#<object "
767 (object-class-name rtx)
774 ; Dump an expression to a string.
776 (define (rtx-strdump rtx)
777 (with-output-to-string
779 ;; Use write instead of display, we want strings displayed with quotes.
780 (write (rtx-dump rtx))))
783 ; Return a boolean indicating if EXPR is known to be a compile-time constant.
785 (define (rtx-compile-time-constant? expr)
790 ((memq expr '(FALSE TRUE)) #t)
794 ; Return boolean indicating if EXPR has side-effects.
795 ; FIXME: for now punt.
797 (define (rtx-side-effects? expr)
801 ; Return a boolean indicating if EXPR is a "true" boolean value.
803 ; ??? In RTL, #t is a synonym for (const 1). This is confusing for Schemers,
804 ; so maybe RTL's #t should be renamed to TRUE.
806 (define (rtx-true? expr)
809 ((const enum) (!= (rtx-constant-value expr) 0))
811 ((eq? expr 'TRUE) #t)
815 ; Return a boolean indicating if EXPR is a "false" boolean value.
817 ; ??? In RTL, #f is a synonym for (const 0). This is confusing for Schemers,
818 ; so maybe RTL's #f should be renamed to FALSE.
820 (define (rtx-false? expr)
823 ((const enum) (= (rtx-constant-value expr) 0))
825 ((eq? expr 'FALSE) #t)
829 ; Return canonical boolean values.
831 (define (rtx-false) (rtx-make-const 'BI 0))
832 (define (rtx-true) (rtx-make-const 'BI 1))
834 ; Convert EXPR to a canonical boolean if possible.
836 (define (rtx-canonical-bool expr)
837 (cond ((rtx-side-effects? expr) expr)
838 ((rtx-false? expr) (rtx-false))
839 ((rtx-true? expr) (rtx-true))
843 ; Return rtx values for #f/#t.
845 (define (rtx-make-bool value)
851 ; Return #t if X is an rtl expression.
852 ; e.g. '(add WI dr simm8);
856 (and (pair? x) ; pair? -> cheap non-null-list?
857 (or (hashq-ref /rtx-func-table (car x))
858 (hashq-ref /rtx-macro-table (car x)))))
861 ; Instruction field support.
863 ; Return list of ifield names refered to in EXPR.
864 ; Assumes EXPR is more than just (ifield x).
866 (define (rtl-find-ifields expr)
868 (letrec ((scan! (lambda (arg-list)
869 (for-each (lambda (arg)
871 (if (eq? (car arg) 'ifield)
873 (cons (rtx-ifield-name arg)
878 (nub ifields identity)))
881 ; Hardware rtx handlers.
883 ; Subroutine of hw to compute the object's name.
884 ; The name of the operand must include the index so that multiple copies
885 ; of a hardware object (e.g. h-gr[0], h-gr[14]) can be distinguished.
886 ; We make some attempt to make the name pretty as it appears in generated
889 (define (/rtx-hw-name hw hw-name index-arg)
890 (cond ((hw-scalar? hw)
893 (symbolstr-append hw-name '- (rtx-pretty-name index-arg)))
895 (symbolstr-append hw-name ; (obj:name (op:type self))
897 ; (obj:name (op:index self)))))
898 (stringize index-arg "-"))))
901 ; Return the <operand> object described by
902 ; HW-NAME/MODE-NAME/SELECTOR/INDEX-ARG.
904 ; HW-NAME is the name of the hardware element.
905 ; INDEX-ARG is an rtx or number of the index.
906 ; In the case of scalar hardware elements, pass 0 for INDEX-ARG.
907 ; MODE-NAME is the name of the mode.
908 ; In the case of a vector of registers, INDEX-ARG is the vector index.
909 ; In the case of a scalar register, the value is ignored, but pass 0 (??? #f?).
910 ; SELECTOR is an rtx or number and is passed to HW-NAME to allow selection of a
911 ; particular variant of the hardware. It's kind of like an INDEX, but along
912 ; an atypical axis. An example is memory ASI's on Sparc. Pass
913 ; hw-selector-default if there is no selector.
914 ; ESTATE is the current rtx evaluation state.
916 ; e.g. (hw estate WI h-gr #f (const INT 14))
917 ; selects register 14 of the h-gr set of registers.
919 ; *** The index is passed unevaluated because for parallel execution support
920 ; *** a variable is created with a name based on the hardware element and
921 ; *** index, and we want a reasonably simple and stable name. We get this by
922 ; *** stringize-ing it.
923 ; *** ??? Though this needs to be redone anyway.
925 ; ??? The specified hardware element must be either a scalar or a vector.
926 ; Maybe in the future allow arrays although there's significant utility in
927 ; allowing only at most a scalar index.
929 (define (hw estate mode-name hw-name index-arg selector)
930 ; Enforce some rules to keep things in line with the current design.
931 (if (not (symbol? mode-name))
932 (parse-error (estate-context estate) "invalid mode name" mode-name))
933 (if (not (symbol? hw-name))
934 (parse-error (estate-context estate) "invalid hw name" hw-name))
935 (if (not (or (number? index-arg)
937 (parse-error (estate-context estate) "invalid index" index-arg))
938 (if (not (or (number? selector)
940 (parse-error (estate-context estate) "invalid selector" selector))
942 (let ((hw (current-hw-sem-lookup-1 hw-name)))
944 (parse-error (estate-context estate) "invalid hardware element" hw-name))
946 (let* ((mode (if (eq? mode-name 'DFLT) (hw-mode hw) (mode:lookup mode-name)))
947 (hw-name-with-mode (symbol-append hw-name '- (obj:name mode)))
948 (result (new <operand>))) ; ??? lookup-for-new?
951 (parse-error (estate-context estate) "invalid mode" mode-name))
953 ; Record the selector.
954 (elm-xset! result 'selector selector)
956 ; Create the index object.
957 (elm-xset! result 'index
958 (cond ((number? index-arg)
959 (make <hw-index> 'anonymous 'constant UINT index-arg))
961 ; For the simulator the following could be done which
962 ; would save having to create a closure.
963 ; ??? Old code, left in for now.
964 ; (rtx-get estate DFLT
965 ; (rtx-eval (estate-context estate)
966 ; (estate-econfig estate)
967 ; index-arg rtx-evaluator))
968 ; Make sure constant indices are recorded as such.
969 (if (rtx-constant? index-arg)
970 (make <hw-index> 'anonymous 'constant UINT
971 (rtx-constant-value index-arg))
972 (make <hw-index> 'anonymous 'rtx DFLT
973 (/rtx-closure-make estate index-arg))))
974 (else (parse-error (estate-context estate)
975 "invalid index" index-arg))))
977 (if (not (hw-mode-ok? hw (obj:name mode) (elm-xget result 'index)))
978 (parse-error (estate-context estate)
979 "invalid mode for hardware" mode-name))
981 (elm-xset! result 'hw-name hw-name)
982 (elm-xset! result 'type hw)
983 (elm-xset! result 'mode-name mode-name)
984 (elm-xset! result 'mode mode)
986 (op:set-pretty-sem-name! result hw-name)
988 ; The name of the operand must include the index so that multiple copies
989 ; of a hardware object (e.g. h-gr[0], h-gr[14]) can be distinguished.
990 (let ((name (/rtx-hw-name hw hw-name-with-mode index-arg)))
991 (send result 'set-name! name)
992 (op:set-sem-name! result name))
994 ; Empty comment and attribute.
995 ; ??? Stick the arguments in the comment for debugging purposes?
996 (send result 'set-comment! "")
997 (send result 'set-atlist! atlist-empty)
1002 ; This is shorthand for (hw estate mode hw-name regno selector).
1003 ; ESTATE is the current rtx evaluation state.
1004 ; INDX-SEL is an optional register number and possible selector.
1005 ; The register number, if present, is (car indx-sel) and must be a number or
1006 ; unevaluated RTX expression.
1007 ; The selector, if present, is (cadr indx-sel) and must be a number or
1008 ; unevaluated RTX expression.
1009 ; ??? A register selector isn't supported yet. It's just an idea that's
1010 ; been put down on paper for future reference.
1012 (define (reg estate mode-name hw-name . indx-sel)
1013 (s-hw estate mode-name hw-name
1014 (if (pair? indx-sel) (car indx-sel) 0)
1015 (if (and (pair? indx-sel) (pair? (cdr indx-sel)))
1017 hw-selector-default))
1020 ; This is shorthand for (hw estate mode-name h-memory addr selector).
1021 ; ADDR must be an unevaluated RTX expression.
1022 ; If present (car sel) must be a number or unevaluated RTX expression.
1024 (define (mem estate mode-name addr . sel)
1025 (s-hw estate mode-name 'h-memory addr
1026 (if (pair? sel) (car sel) hw-selector-default))
1029 ; For the rtx nodes to use.
1033 ; The program counter.
1034 ; When this code is loaded, global `pc' is nil, it hasn't been set to the
1035 ; pc operand yet (see operand-init!). We can't use `pc' inside the drn as the
1036 ; value is itself. So we use s-pc. rtl-finish! must be called after
1041 ; Conditional execution.
1043 ; `if' in RTL has a result, like ?: in C.
1044 ; We support both: one with a result (non VOID mode), and one without (VOID mode).
1045 ; The non-VOID case must have an else part.
1046 ; MODE is the mode of the result, not the comparison.
1047 ; The comparison is expected to return a zero/non-zero value.
1048 ; ??? Perhaps this should be a syntax-expr. Later.
1050 (define (e-if estate mode cond then . else)
1051 (if (> (length else) 1)
1052 (estate-error estate "if: too many elements in `else' part" else))
1055 (if cond then (car else)))
1059 ; ??? Not sure this should live here.
1061 (define (/subr-read context . arg-list)
1067 (let ((s (apply /subr-read (cons "define-subr" arg-list))))
1069 (current-subr-add! s))
1075 ; The argument to drn,drmn,drsn must be Scheme code (or a fixed subset
1076 ; thereof). .str/.sym are used in pmacros so it makes sense to include them
1078 (define .str string-append)
1079 (define .sym symbol-append)
1081 ; Given (expr1 expr2 expr3 expr4), for example,
1082 ; return (fn (fn (fn expr1 expr2) expr3) expr4).
1084 (define (rtx-combine fn exprs)
1085 (assert (not (null? exprs)))
1086 (letrec ((-rtx-combine (lambda (fn exprs result)
1094 (-rtx-combine fn (cdr exprs) (car exprs)))
1097 ; Called before a .cpu file is read in.
1100 (set! /rtx-func-table (make-hash-table 127))
1101 (set! /rtx-macro-table (make-hash-table 127))
1102 (set! /rtx-num-next 0)
1106 ; All rtx take options for the first arg and a mode for the second.
1107 (for-each (lambda (rtx-name)
1108 (let ((rtx (rtx-lookup rtx-name)))
1111 (if (null? (rtx-arg-types rtx))
1112 #f ; pc is the one exception, blech
1114 (assert (eq? (car (rtx-arg-types rtx)) 'OPTIONS))
1115 (assert (memq (cadr (rtx-arg-types rtx)) /rtx-valid-mode-types)))))
1120 (reader-add-command! 'define-subr
1122 Define an rtx subroutine, name/value pair list version.
1124 nil 'arg-list define-subr)
1130 (define (rtl-builtin!)
1134 ; Called after cpu files are loaded to add misc. remaining entries to the
1135 ; rtx handler table for use during evaluation.
1136 ; rtl-finish! must be done before ifmt-compute!, the latter will
1137 ; construct hardware objects which is done by rtx evaluation.
1139 (define (rtl-finish!)
1140 (logit 2 "Building rtx operand table ...\n")
1142 ; Update s-pc, must be called after operand-init!.
1145 ; Table of traversers for the various rtx elements.
1146 (let ((hash-table (/rtx-make-traverser-table)))
1147 (set! /rtx-traverser-table (make-vector (rtx-max-num) #f))
1148 (for-each (lambda (rtx-name)
1149 (let ((rtx (rtx-lookup rtx-name)))
1151 (vector-set! /rtx-traverser-table (rtx-num rtx)
1155 (hashq-ref hash-table arg-type)))
1156 (rtx-arg-types rtx))))))
1159 ; Initialize the operand hash table.
1160 (set! /rtx-operand-table (make-hash-table 127))
1162 ; Add the operands to the eval symbol table.
1163 (for-each (lambda (op)
1164 (hashq-set! /rtx-operand-table (obj:name op) op))
1167 ; Add ifields to the eval symbol table.
1168 (for-each (lambda (f)
1169 (hashq-set! /rtx-operand-table (obj:name f) f))
1170 (non-derived-ifields (current-ifld-list)))