OSDN Git Service

Specify isa(s) when doing ifield, operand, insn lookups.
authordevans <devans>
Tue, 3 Nov 2009 16:24:01 +0000 (16:24 +0000)
committerdevans <devans>
Tue, 3 Nov 2009 16:24:01 +0000 (16:24 +0000)
ACU = all callers updated.
* attr.scm (/attr-eval): Call rtx-value instead of rtx-eval-with-estate.
* enum.scm (define-full-insn-enum): Pass isa-name-list to
current-ifld-lookup.
* html.scm (get-insn-properties): Pass isa-name-list to
current-op-lookup.
* ifield.scm (/ifld-parse-follows): New arg isas, ACU.
* insn.scm (/parse-insn-format-symbol): New arg isa-name-list, ACU.
(/parse-insn-format-list, /parse-insn-iformat-iflds): Ditto.
(/parse-insn-format, syntax-break-out): Ditto.
* mach.scm (obj-filter-by-isa): New function.
(current-ifld-lookup): New optional arg maybe-isa-name-list.
(/ifld-already-defined?, /op-already-defined?): Simplify.
(current-op-lookup): New optional arg maybe-isa-name-list.
(current-insn-lookup): New arg isa-name-list, ACU.
(/insn-already-defined?, /minsn-already-defined?): Simplify.
(current-minsn-lookup): New arg isa-name-list, ACU.
* minsn.scm (/minsn-compute-iflds): Pass isa-name-list to
current-op-lookup.
* opc-itab.scm (compute-syntax): New arg isa-name-list, ACU.
(gen-syntax-entry): Ditto.
* operand.scm (/operand-parse): Pass isa-name-list to
current-ifld-lookup.
(/derived-parse-encoding): New arg isa-name-list, ACU.
(/derived-parse-ifield-assertion): Ditto.
(/derived-operand-parse): Pass isa-name-list to current-op-lookup.
(/anyof-parse-choice): Ditto.
(anyof-satisfies-assertions?): Pass context to rtx-solve.
(/anyof-merge-syntax): New arg container, ACU.
(operand-builtin!): Add pc to all isas.
* rtl-c.scm (estate-make-for-rtl-c): Delete arg extra-vars-alist, ACU.
(estate-make-for-rtl-c++, rtl-c-expr-parsed): Ditto.
(rtl-c-parsed, rtl-c++-parsed): Ditto.
(rtl-c): New arg isa-name-list, ACU.
(rtl-c-expr, rtl-c++): Ditto.
(closure): New arg isa-name-list, ACU.
* rtl-traverse.scm (/make-cstate): New arg isa-name-list, ACU.
(/cstate-isas): New function.
(/rtx-canon-symbol-list): New function.
(/rtx-canon-env-stack): Renamed from /rtx-canon-env, ACU.
updated.
(/rtx-make-canon-table): Rename ENV to ENVSTACK, new entry SYMBOLLIST.
(/rtx-canon-rtx-operand): Pass isa list to current-op-lookup.
(/rtx-canon-rtx-ref, /rtx-canon): Ditto.
(rtx-canonicalize): New arg isa-name-list, ACU.
(rtx-canonicalize-stmt): Delete.
(tstate-make): New arg isas, ACU.
(tstate-isas, tstate--set-isas!): New functions.
(tstate-env-stack): Renamed from tstate-env, ACU.
(tstate-set-env-stack!): Renamed from tstate-set-env!, ACU.
(tstate-make-closure): Renamed from tstate-new-env, new arg
isa-name-list, ACU.
(/rtx-traverse-env): Delete.
(/rtx-make-traverser-table): Rename ENV to ENVSTACK, new entry
SUMBOLLIST.
(/rtx-traverse): Include conditional flag in dump output.
Update isa,envstack for closures.  Pass isa list to current-op-lookup.
(<eval-state>): New member isas.  Rename env to env-stack.
(<eval-state> vmake!): Handle #:isas.  #:env renamed to #:env-stack.
(<eval-state>): New getter/setter for isas.  Rename env getter/setter
to env-stack.
(estate-make-for-eval): Provide #:isas.
(estate-make-closure): Renamed from estate-new-env.  New arg
isa-name-list, ACU.
* rtl-xform.scm (/rtx-simplify-expr-fn): Handle closures.
(/rtx-trim-args): ENV renamed to ENVSTACK.  Ad ITERATION, SYMBOLLIST.
(/rtx-trim-for-doc): Handle closures.
* rtl.scm (/rtx-valid-types): Rename ENV to ENVSTACK.  Add ITERATION,
SYMBOLLIST.
(rtx-env-var-list): Delete.
(rtx-env-make): Handle already-compiled environments.
(rtx-var-alist-to-env): New function.
(rtx-var-alist-to-closure-env-stack, rtx-make-env-stack): New functions.
(rtx-env-stack-dump): Renamed from rtx-env-dump, ACU.
(rtx-operand-obj): New arg isa-name-list, ACU.
(rtx-closure-isas, rtx-closure-env-stack, rtx-closure-expr): New
functions.
* rtx-funcs.scm (closure): New arg isa-name-list, reorder args, ACU.
* sem-frags.scm (<sfrag>): Delete member compiled-semantics.
(/frag-compute-desired-frags): Minor simplification.
(/frag-pick-best): Ditto.
* sid-cpu.scm (gen-semantic-code): Require canonical rtl.
(/gen-sfrag-code): Update.
* sim-cpu.scm (gen-semantic-code): Require canonical rtl.
* utils-cgen.scm (sanitize): New arg isa-name-list, ACU.
* utils.scm (non-null-intersection?): New function.

32 files changed:
cgen/ChangeLog
cgen/attr.scm
cgen/desc-cpu.scm
cgen/enum.scm
cgen/gas-test.scm
cgen/html.scm
cgen/ifield.scm
cgen/insn.scm
cgen/intrinsics.scm
cgen/mach.scm
cgen/minsn.scm
cgen/opc-itab.scm
cgen/opcodes.scm
cgen/operand.scm
cgen/read.scm
cgen/rtl-c.scm
cgen/rtl-traverse.scm
cgen/rtl-xform.scm
cgen/rtl.scm
cgen/rtx-funcs.scm
cgen/sem-frags.scm
cgen/semantics.scm
cgen/sid-cpu.scm
cgen/sid-decode.scm
cgen/sid.scm
cgen/sim-cpu.scm
cgen/sim-decode.scm
cgen/sim-test.scm
cgen/sim.scm
cgen/utils-cgen.scm
cgen/utils-gen.scm
cgen/utils.scm

index e3f2689..c3f5b86 100644 (file)
@@ -1,5 +1,93 @@
 2009-11-02  Doug Evans  <dje@sebabeach.org>
 
+       Specify isa(s) when doing ifield, operand, insn lookups.
+       ACU = all callers updated.
+       * attr.scm (/attr-eval): Call rtx-value instead of rtx-eval-with-estate.
+       * enum.scm (define-full-insn-enum): Pass isa-name-list to
+       current-ifld-lookup.
+       * html.scm (get-insn-properties): Pass isa-name-list to
+       current-op-lookup.
+       * ifield.scm (/ifld-parse-follows): New arg isas, ACU.
+       * insn.scm (/parse-insn-format-symbol): New arg isa-name-list, ACU.
+       (/parse-insn-format-list, /parse-insn-iformat-iflds): Ditto.
+       (/parse-insn-format, syntax-break-out): Ditto.
+       * mach.scm (obj-filter-by-isa): New function.
+       (current-ifld-lookup): New optional arg maybe-isa-name-list.
+       (/ifld-already-defined?, /op-already-defined?): Simplify.
+       (current-op-lookup): New optional arg maybe-isa-name-list.
+       (current-insn-lookup): New arg isa-name-list, ACU.
+       (/insn-already-defined?, /minsn-already-defined?): Simplify.
+       (current-minsn-lookup): New arg isa-name-list, ACU.
+       * minsn.scm (/minsn-compute-iflds): Pass isa-name-list to
+       current-op-lookup.
+       * opc-itab.scm (compute-syntax): New arg isa-name-list, ACU.
+       (gen-syntax-entry): Ditto.
+       * operand.scm (/operand-parse): Pass isa-name-list to
+       current-ifld-lookup.
+       (/derived-parse-encoding): New arg isa-name-list, ACU.
+       (/derived-parse-ifield-assertion): Ditto.
+       (/derived-operand-parse): Pass isa-name-list to current-op-lookup.
+       (/anyof-parse-choice): Ditto.
+       (anyof-satisfies-assertions?): Pass context to rtx-solve.
+       (/anyof-merge-syntax): New arg container, ACU.
+       (operand-builtin!): Add pc to all isas.
+       * rtl-c.scm (estate-make-for-rtl-c): Delete arg extra-vars-alist, ACU.
+       (estate-make-for-rtl-c++, rtl-c-expr-parsed): Ditto.
+       (rtl-c-parsed, rtl-c++-parsed): Ditto.
+       (rtl-c): New arg isa-name-list, ACU.
+       (rtl-c-expr, rtl-c++): Ditto.
+       (closure): New arg isa-name-list, ACU.
+       * rtl-traverse.scm (/make-cstate): New arg isa-name-list, ACU.
+       (/cstate-isas): New function.
+       (/rtx-canon-symbol-list): New function.
+       (/rtx-canon-env-stack): Renamed from /rtx-canon-env, ACU.
+       updated.
+       (/rtx-make-canon-table): Rename ENV to ENVSTACK, new entry SYMBOLLIST.
+       (/rtx-canon-rtx-operand): Pass isa list to current-op-lookup.
+       (/rtx-canon-rtx-ref, /rtx-canon): Ditto.
+       (rtx-canonicalize): New arg isa-name-list, ACU.
+       (rtx-canonicalize-stmt): Delete.
+       (tstate-make): New arg isas, ACU.
+       (tstate-isas, tstate--set-isas!): New functions.
+       (tstate-env-stack): Renamed from tstate-env, ACU.
+       (tstate-set-env-stack!): Renamed from tstate-set-env!, ACU.
+       (tstate-make-closure): Renamed from tstate-new-env, new arg
+       isa-name-list, ACU.
+       (/rtx-traverse-env): Delete.
+       (/rtx-make-traverser-table): Rename ENV to ENVSTACK, new entry
+       SUMBOLLIST.
+       (/rtx-traverse): Include conditional flag in dump output.
+       Update isa,envstack for closures.  Pass isa list to current-op-lookup.
+       (<eval-state>): New member isas.  Rename env to env-stack.
+       (<eval-state> vmake!): Handle #:isas.  #:env renamed to #:env-stack.
+       (<eval-state>): New getter/setter for isas.  Rename env getter/setter
+       to env-stack.
+       (estate-make-for-eval): Provide #:isas.
+       (estate-make-closure): Renamed from estate-new-env.  New arg
+       isa-name-list, ACU.
+       * rtl-xform.scm (/rtx-simplify-expr-fn): Handle closures.
+       (/rtx-trim-args): ENV renamed to ENVSTACK.  Ad ITERATION, SYMBOLLIST.
+       (/rtx-trim-for-doc): Handle closures.
+       * rtl.scm (/rtx-valid-types): Rename ENV to ENVSTACK.  Add ITERATION,
+       SYMBOLLIST.
+       (rtx-env-var-list): Delete.
+       (rtx-env-make): Handle already-compiled environments.
+       (rtx-var-alist-to-env): New function.
+       (rtx-var-alist-to-closure-env-stack, rtx-make-env-stack): New functions.
+       (rtx-env-stack-dump): Renamed from rtx-env-dump, ACU.
+       (rtx-operand-obj): New arg isa-name-list, ACU.
+       (rtx-closure-isas, rtx-closure-env-stack, rtx-closure-expr): New
+       functions.
+       * rtx-funcs.scm (closure): New arg isa-name-list, reorder args, ACU.
+       * sem-frags.scm (<sfrag>): Delete member compiled-semantics.
+       (/frag-compute-desired-frags): Minor simplification.
+       (/frag-pick-best): Ditto.
+       * sid-cpu.scm (gen-semantic-code): Require canonical rtl.
+       (/gen-sfrag-code): Update.
+       * sim-cpu.scm (gen-semantic-code): Require canonical rtl.
+       * utils-cgen.scm (sanitize): New arg isa-name-list, ACU.
+       * utils.scm (non-null-intersection?): New function.
+
        * gen-all (do_src): Manually run cgen-all for sid.
 
 2009-11-01  Doug Evans  <dje@sebabeach.org>
index 80c8ca9..baf69c0 100644 (file)
 ; Expand attribute value ATVAL, which is an rtx expression.
 ; OWNER is the containing object or #f if there is none.
 ; OWNER is needed if an attribute is defined in terms of other attributes.
-; If it's #f obviously ATVAL can't be defined in terms of others.
+; OWNER is also needed to get the ISA(s) in which to evaluate the expression.
+; If it's #f obviously ATVAL can't be defined in terms of others,
+; or refer to operands that require an ISA to disambiguate.
 
 (define (/attr-eval atval owner)
-  (let* ((estate (estate-make-for-eval #f owner))
-        (atval-expr (car atval))
-        (expr (rtx-simplify #f owner (rtx-canonicalize #f 'DFLT atval-expr nil) nil))
-        (value (rtx-eval-with-estate expr DFLT estate)))
+  (let* ((atval-expr (car atval))
+        (expr (rtx-simplify #f owner
+                            (rtx-canonicalize #f 'DFLT
+                                              (and owner (obj-isa-list owner))
+                                              nil atval-expr)
+                            nil))
+        (value (rtx-value expr owner)))
     (cond ((symbol? value) value)
          ((number? value) value)
          (error "/attr-eval: internal error, unsupported result:" value)))
index 272f708..5189916 100644 (file)
@@ -331,7 +331,8 @@ const CGEN_HW_ENTRY @arch@_cgen_hw_table[] =
    "#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS "
    ; The +2 account for the leading "MNEM" and trailing 0.
    (number->string (+ 2 (apply max (map (lambda (insn) 
-                                         (length (syntax-break-out (insn-syntax insn))))
+                                         (length (syntax-break-out (insn-syntax insn)
+                                                                   (obj-isa-list insn))))
                                        (current-insn-list)))))
    "\n"
    "\n"
index ec02c06..49cbb07 100644 (file)
 
 (define (define-full-insn-enum name comment attrs prefix fld vals)
   (let* ((context (make-current-context "define-full-insn-enum"))
-        (atlist (atlist-parse context attrs "insn-enum"))
-        (fld-obj (current-ifld-lookup fld)))
+        (atlist-obj (atlist-parse context attrs "insn-enum"))
+        (isa-name-list (atlist-attr-value atlist-obj 'ISA #f))
+        (fld-obj (current-ifld-lookup fld isa-name-list)))
 
-    (if (keep-isa-atlist? atlist #f)
+    (if (keep-isa-atlist? atlist-obj #f)
        (begin
          (if (not fld-obj)
              (parse-error context "unknown insn field" fld))
          (let ((e (make <insn-enum>
                     (parse-name context name)
                     (parse-comment context comment)
-                    atlist
+                    atlist-obj
                     (/enum-parse-prefix context prefix)
                     fld-obj
                     (parse-enum-vals context prefix vals))))
index 996436d..b06c588 100644 (file)
@@ -20,7 +20,8 @@
 (define (gas-test-analyze!)
   (opcodes-analyze!)
   (map (lambda (insn)
-        (elm-xset! insn 'tmp (syntax-break-out (insn-syntax insn))))
+        (elm-xset! insn 'tmp (syntax-break-out (insn-syntax insn)
+                                               (obj-isa-list insn))))
        (non-multi-insns (current-insn-list)))
   *UNSPECIFIED*
 )
index 00d2730..83f3ed0 100644 (file)
@@ -693,7 +693,8 @@ See the input .cpu file(s) for copyright information.
        (lambda (rtx-obj expr parent-expr op-pos tstate appstuff)
          (case (car expr)
 
-           ((operand) (if (memory? (op:type (current-op-lookup (rtx-arg1 expr))))
+           ((operand) (if (memory? (op:type (current-op-lookup (rtx-arg1 expr)
+                                                               (obj-isa-list insn))))
                           ; Don't change to '(MEM), since we use append!.
                           (append! sem-attrs (list 'MEM)))
                       (if (mode-float? (mode:lookup (rtx-mode expr)))
index 2709e51..f8da65e 100644 (file)
              (flength (parse-number context flength '(0 . 127)))
              (lsb0? (current-arch-insn-lsb0?))
              (mode-obj (parse-mode-name context mode))
-             (follows-obj (/ifld-parse-follows context follows))
+             (follows-obj (/ifld-parse-follows context follows isas))
              )
 
          ; Calculate the <bitrange> object.
 
 ; Parse a `follows' spec.
 
-(define (/ifld-parse-follows context follows)
+(define (/ifld-parse-follows context follows isas)
   (if follows
-      (let ((follows-obj (current-op-lookup follows)))
+      (let ((follows-obj (current-op-lookup follows isas)))
        (if (not follows-obj)
            (parse-error context "unknown operand to follow" follows))
        follows-obj)
index 459c1a8..0281401 100644 (file)
                     (obj:comment insn)
                     (obj-atlist insn)
                     (/anyof-merge-syntax (insn-syntax insn)
-                                         value-names new-values)
+                                         value-names new-values insn)
                     ifields
                     (insn-ifield-assertion insn) ; FIXME
                     (anyof-merge-semantics (insn-semantics insn)
   (let* ((name (parse-name context name))
         (context (context-append-name context name))
         (atlist-obj (atlist-parse context attrs "cgen_insn"))
-        (isas (atlist-attr-value atlist-obj 'ISA #f)))
+        (isa-name-list (atlist-attr-value atlist-obj 'ISA #f)))
+
+    ;; Verify all specified ISAs are valid.
+    (if (not (all-true? (map current-isa-lookup isa-name-list)))
+       (parse-error context "unknown isa in isa list" isa-name-list))
 
     (if (keep-atlist? atlist-obj #f)
 
        (let ((ifield-assertion (if (and ifield-assertion
                                         (not (null? ifield-assertion)))
-                                   (rtx-canonicalize context 'DFLT ;; BI?
-                                                     ifield-assertion nil)
+                                   (rtx-canonicalize context
+                                                     'DFLT ;; BI?
+                                                     isa-name-list nil
+                                                     ifield-assertion)
                                    #f))
              (semantics (if (not (null? semantics))
                             semantics
                       (context-append context " format")
                       (and (not (atlist-has-attr? atlist-obj 'VIRTUAL))
                            (reader-verify-iformat? CURRENT-READER))
-                      ;; Just pick the first, the base len
-                      ;; for each should be the same.
-                      ;; If not this is caught by
-                      ;; compute-insn-base-mask-length.
-                      (current-isa-lookup (car isas))
+                      isa-name-list
                       fmt))
              (comment (parse-comment context comment))
              ; If there are no semantics, mark this as an alias.
 
 ; Subroutine of /parse-insn-format to parse a symbol ifield spec.
 
-(define (/parse-insn-format-symbol context sym)
+(define (/parse-insn-format-symbol context isa-name-list sym)
   ;(debug-repl-env sym)
-  (let ((op (current-op-lookup sym)))
+  (let ((op (current-op-lookup sym isa-name-list)))
     (if op
        (cond ((derived-operand? op)
               ; There is a one-to-one relationship b/w derived operands and
 ; ??? There is room for growth in the specification syntax here.
 ; Possibilities are (ifield-name|operand-name [options] [value]).
 
-(define (/parse-insn-format-list context spec)
-  (let ((ifld (current-ifld-lookup (car spec))))
+(define (/parse-insn-format-list context isa-name-list spec)
+  (let ((ifld (current-ifld-lookup (car spec) isa-name-list)))
     (if ifld
        (/parse-insn-format-ifield-spec context ifld spec)
        (parse-error context "unknown ifield" spec)))
 
 ; Subroutine of /parse-insn-format to simplify it.
 ; Parse the provided iformat spec and return the list of ifields.
+; ISA-NAME-lIST is the ISA attribute of the containing insn.
 
-(define (/parse-insn-iformat-iflds context fld-list)
+(define (/parse-insn-iformat-iflds context isa-name-list fld-list)
   (if (null? fld-list)
       nil ; field list unspecified
       (case (car fld-list)
                                 (string->symbol fld)
                                 fld)))
                      (cond ((symbol? f)
-                            (/parse-insn-format-symbol context f))
+                            (/parse-insn-format-symbol context isa-name-list f))
                            ((and (list? f)
                                  ; ??? This use to allow <ifield> objects
                                  ; in the `car' position.  Checked for below.
                                  (symbol? (car f)))
-                            (/parse-insn-format-list context f))
+                            (/parse-insn-format-list context isa-name-list f))
                            (else
                             (if (and (list? f)
                                      (ifield? (car f)))
                   (parse-error context
                                "bad `=' format spec, should be `(= insn-name)'"
                                fld-list))
-              (let ((insn (current-insn-lookup (cadr fld-list))))
+              (let ((insn (current-insn-lookup (cadr fld-list) isa-name-list)))
                 (if (not insn)
                     (parse-error context "unknown insn" (cadr fld-list)))
                 (insn-iflds insn))))
 
 ; Given an insn format field from a .cpu file, replace it with a list of
 ; ifield objects with the values assigned.
-; ISA is an <isa> object or #f.
-; If VERIFY? is non-#f, perform various checks on the format
-; (ISA must be an <isa> object).
+; ISA-NAME-LIST is the ISA attribute of the containing insn.
+; If VERIFY? is non-#f, perform various checks on the format.
 ;
 ; An insn format field is a list of ifields that make up the instruction.
 ; All bits must be specified, including reserved bits
 ; It's called for each instruction, and is one of the more expensive routines
 ; in insn parsing.
 
-(define (/parse-insn-format context verify? isa ifld-list)
-  (let* ((parsed-ifld-list (/parse-insn-iformat-iflds context ifld-list)))
+(define (/parse-insn-format context verify? isa-name-list ifld-list)
+  (let* ((parsed-ifld-list
+         (/parse-insn-iformat-iflds context isa-name-list ifld-list)))
 
     ;; NOTE: We could sort the fields here, but it introduces differences
     ;; in the generated opcodes files.  Later it might be a good thing to do
 
     (if verify?
 
-       (let ((base-len (isa-base-insn-bitsize isa))
-             (pretty-print-iflds (lambda (iflds)
-                                   (if (null? iflds)
-                                       " none provided"
-                                       (string-map (lambda (f)
-                                                     (string-append " "
-                                                                    (ifld-pretty-print f)))
-                                                   iflds)))))
+       ;; Just pick the first ISA, the base len for each should be the same.
+       ;; If not this is caught by compute-insn-base-mask-length.
+       (let* ((isa (current-isa-lookup (car isa-name-list)))
+              (base-len (isa-base-insn-bitsize isa))
+              (pretty-print-iflds (lambda (iflds)
+                                    (if (null? iflds)
+                                        " none provided"
+                                        (string-map (lambda (f)
+                                                      (string-append " "
+                                                                     (ifld-pretty-print f)))
+                                                    iflds)))))
 
          ;; Perform some error checking.
          ;; Look for overlapping ifields and missing bits.
 ; Create a list of syntax strings broken up into a list of characters and
 ; operand objects.
 
-(define (syntax-break-out syntax)
+(define (syntax-break-out syntax isa-name-list)
   (let ((result nil))
     ; ??? The style of the following could be more Scheme-like.  Later.
     (let loop ()
                  (let ((n (string-index syntax #\})))
                    (set! result (cons (current-op-lookup
                                        (string->symbol
-                                        (substring syntax 2 n)))
+                                        (substring syntax 2 n))
+                                       isa-name-list)
                                       result))
                    (set! syntax (string-drop (+ 1 n) syntax)))
                  (let ((n (id-len (string-drop1 syntax))))
                    (set! result (cons (current-op-lookup
                                        (string->symbol
-                                        (substring syntax 1 (+ 1 n))))
+                                        (substring syntax 1 (+ 1 n)))
+                                       isa-name-list)
                                       result))
                    (set! syntax (string-drop (+ 1 n) syntax)))))
             ; Handle everything else.
index f59b602..ee25a95 100644 (file)
         ;; each cgen operand is replaced by an md-operand.
         (syntax (map (lambda (x)
                        (if (operand? x) (make-operand x) x))
-                     (syntax-break-out (insn-syntax insn))))
+                     (syntax-break-out (insn-syntax insn)
+                                       (obj-isa-list insn))))
 
         ;; All relevant outputs.
         (outputs (find (lambda (op)
index 732e5c2..8750239 100644 (file)
   (object-assq isa-name (current-isa-list))
 )
 
+;; Given a list of objects OBJ-LIST, return those objects that are from the
+;; ISA(s) in ISA-NAME-LIST.
+;; ISA-NAME-LIST may be (all) or #f (which also means (all)).
+
+(define (obj-filter-by-isa obj-list isa-name-list)
+  (if (or (eq? isa-name-list #f)
+         (memq 'all isa-name-list))
+      obj-list
+      (find (lambda (obj)
+             (let ((obj-isas (obj-attr-value obj 'ISA)))
+               (non-null-intersection? obj-isas isa-name-list)))
+           obj-list))
+)
+
 ; Cpu families.
 
 (define (current-cpu-list) (arch-cpu-list CURRENT-ARCH))
 )
 
 ;; Look up ifield X in the current architecture.
+;; Returns the <ifield> object or #f if not found.
+;; If there is an ambiguity (i.e. the ifield is in multiple ISAs and
+;; MAYBE-ISA-NAME-LIST doesn't disambiguate the choice) an error is signalled.
 ;;
 ;; If X is an <ifield> object, just return it.
 ;; This is to handle ???
 ;; Otherwise X is the name of the ifield to look up.
-;;
-;; ??? This doesn't work if there are multiple operands with the same name
-;; for different isas.
+;; If MAYBE-ISA-NAME-LIST is provided, the car is a list of ISAs to look in.
+;; If the specified isa list is #f, look in all ISAs.
 
-(define (current-ifld-lookup x)
+(define (current-ifld-lookup x . maybe-isa-name-list)
   (if (ifield? x)
       x
       (let ((f-list (/ident-object-table-lookup (car (arch-ifld-table CURRENT-ARCH))
                                                x)))
        (if f-list
-           (if (= (length f-list) 1)
-               (car f-list)
-               ;; FIXME: For now just return the first one,
-               ;; same behaviour as before.
-               ;; Here "first one" means "first defined".
-               (/get-lowest-ordinal f-list))
+           (let* ((isas (if (not (null? maybe-isa-name-list)) (car maybe-isa-name-list) #f))
+                  (filtered-f-list (obj-filter-by-isa f-list isas)))
+             (case (length filtered-f-list)
+               ((0) (error "Ifield not in specified ISA:" x))
+               ((1) (car filtered-f-list))
+               (else (error "Ambiguous ifield lookup:" x))))
            #f)))
 )
 
        (let ((result #f)
              (f-isas (obj-isa-list f)))
          (for-each (lambda (ff)
-                     (if (not (null? (intersection f-isas (obj-isa-list ff))))
+                     (if (non-null-intersection? f-isas (obj-isa-list ff))
                          (set! result #t)))
                    iflds)
          result)
   *UNSPECIFIED*
 )
 
-; ??? This doesn't work if there are multiple operands with the same name
-; for different isas.
+;; Look up operand NAME in the current architecture.
+;; Returns the <operand> object or #f if not found.
+;; If there is an ambiguity (i.e. the operand is in multiple ISAs and
+;; MAYBE-ISA-NAME-LIST doesn't disambiguate the choice) an error is signalled.
+;;
+;; If MAYBE-ISA-NAME-LIST is provided, the car is a list of ISAs to look in.
+;; If the specified isa list is #f, look in all ISAs.
 
-(define (current-op-lookup name)
+(define (current-op-lookup name . maybe-isa-name-list)
   (let ((op-list (/ident-object-table-lookup (car (arch-op-table CURRENT-ARCH))
                                             name)))
     (if op-list
-       (if (= (length op-list) 1)
-           (car op-list)
-           ;; FIXME: For now just return the first one, same behaviour as before.
-           ;; Here "first one" means "first defined".
-           (/get-lowest-ordinal op-list))
+       (let* ((isas (if (not (null? maybe-isa-name-list)) (car maybe-isa-name-list) #f))
+              (filtered-o-list (obj-filter-by-isa op-list isas)))
+         (case (length filtered-o-list)
+           ((0) (error "Operand not in specified ISA:" name))
+           ((1) (car filtered-o-list))
+           (else (error "Ambiguous operand lookup:" name))))
        #f))
 )
 
        (let ((result #f)
              (op-isas (obj-isa-list op)))
          (for-each (lambda (o)
-                     (if (not (null? (intersection op-isas (obj-isa-list o))))
+                     (if (non-null-intersection? op-isas (obj-isa-list o))
                          (set! result #t)))
                    ops)
          result)
   *UNSPECIFIED*
 )
 
-; ??? This doesn't work if there are multiple insns with the same name
-; for different isas.
-
-(define (current-insn-lookup name)
-  (let ((i (/ident-object-table-lookup (car (arch-insn-table CURRENT-ARCH))
-                                      name)))
-    (if i
-       (begin
-         (if (= (length i) 1)
-             (car i)
-             ;; FIXME: For now just flag an error.
-             ;; Later add an isa-list arg to distinguish.
-             (error "multiple insns with name:" name)))
+;; Look up insn NAME in the current architecture.
+;; Returns the <insn> object or #f if not found.
+;; If there is an ambiguity (i.e. the insn is in multiple ISAs and
+;; ISA-NAME-LIST doesn't disambiguate the choice) an error is signalled.
+;; If the specified isa list is #f, look in all ISAs.
+
+(define (current-insn-lookup name isa-name-list)
+  (let ((i-list (/ident-object-table-lookup (car (arch-insn-table CURRENT-ARCH))
+                                           name)))
+    (if i-list
+       (let ((filtered-i-list (obj-filter-by-isa i-list isa-name-list)))
+         (case (length filtered-i-list)
+           ((0) (error "Insn not in specified ISA:" name))
+           ((1) (car filtered-i-list))
+           (else (error "Ambiguous insn lookup:" name))))
        #f))
 )
 
        (let ((result #f)
              (insn-isas (obj-isa-list insn)))
          (for-each (lambda (i)
-                     (if (not (null? (intersection insn-isas (obj-isa-list i))))
+                     (if (non-null-intersection? insn-isas (obj-isa-list i))
                          (set! result #t)))
                    insns)
          result)
   *UNSPECIFIED*
 )
 
-; ??? This doesn't work if there are multiple minsns with the same name
-; for different isas.
-
-(define (current-minsn-lookup name)
-  (let ((m (/ident-object-table-lookup (car (arch-minsn-table CURRENT-ARCH))
-                                      name)))
-    (if m
-       (begin
-         (if (= (length m) 1)
-             (car m)
-             ;; FIXME: For now just flag an error.
-             ;; Later add an isa-list arg to distinguish.
-             (error "multiple macro-insns with name:" name)))
+;; Look up minsn NAME in the current architecture.
+;; Returns the <macro-insn> object or #f if not found.
+;; If there is an ambiguity (i.e. the minsn is in multiple ISAs and
+;; ISA-NAME-LIST doesn't disambiguate the choice) an error is signalled.
+;; If the specified isa list is #f, look in all ISAs.
+
+(define (current-minsn-lookup name isa-name-list)
+  (let ((m-list (/ident-object-table-lookup (car (arch-minsn-table CURRENT-ARCH))
+                                           name)))
+    (if m-list
+       (let ((filtered-m-list (obj-filter-by-isa m-list isa-name-list)))
+         (case (length filtered-m-list)
+           ((0) (error "Macro-insn not in specified ISA:" name))
+           ((1) (car filtered-m-list))
+           (else (error "Ambiguous macro-insn lookup:" name))))
        #f))
 )
 
        (let ((result #f)
              (m-isas (obj-isa-list m)))
          (for-each (lambda (mm)
-                     (if (not (null? (intersection m-isas (obj-isa-list mm))))
+                     (if (non-null-intersection? m-isas (obj-isa-list mm))
                          (set! result #t)))
                    minsns)
          result)
                                           nil))))
                         isas)
                    '((max)))))
-    ; Using a bitset attribute here implies something could be used by two
-    ; separate isas.  This seems highly unlikely but we don't [as yet]
-    ; preclude it.  The other thing to consider is whether the cpu table
-    ; would ever want to be opened for multiple isas.
     (define-attr '(type bitset) '(name ISA)
       '(comment "instruction set selection")
       ; If there's only one isa, don't (yet) pollute the tables with a value
                             (make-obj-context insn
                                               (string-append "canonicalizing semantics of "
                                                              (obj:str-name insn)))
-                            'VOID (insn-semantics insn) nil)))
+                            'VOID (obj-isa-list insn) nil
+                            (insn-semantics insn))))
                       (insn-set-canonical-semantics! insn canon-sem)))
                    (else
                     (logit 2 "Skipping instruction " (obj:name insn) ", no semantics ...\n"))))
index 96e0408..3a22906 100644 (file)
         ; 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))))
+        (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
     ; the ifield entry.
     (for-each (lambda (f)
                (let* ((op-name (if (pair? f) (car f) f))
-                      (op-obj (current-op-lookup op-name))
+                      (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
       (parse-error context "not an alias macro-insn" minsn))
 
   (let* ((expn (car (minsn-expansions minsn)))
-        (alias-of (current-insn-lookup (cadr expn))))
+        (alias-of (current-insn-lookup (cadr expn) (obj-isa-list minsn))))
 
     (if (not alias-of)
        (parse-error context "unknown real insn in expansion" minsn))
index 52a8509..bb0697a 100644 (file)
 ; Values < 128 are characters that must be matched.
 ; Values >= 128 are 128 + the index into the operand table.
 
-(define (compute-syntax strip-mnemonic? strip-mnem-operands? syntax op-macro)
+(define (compute-syntax strip-mnemonic? strip-mnem-operands? syntax op-macro
+                       isa-name-list)
   (let ((context (make-prefix-context "syntax computation"))
        (syntax (if strip-mnemonic?
                    (strip-mnemonic strip-mnem-operands? syntax)
                   (if (= n 0)
                       (parse-error context "empty or invalid operand name" syntax))
                   (let ((operand (string->symbol (substring syn 1 (1+ n)))))
-                    (if (not (current-op-lookup operand))
+                    (if (not (current-op-lookup operand isa-name-list))
                         (parse-error context "undefined operand " operand syntax)))
                   (loop (string-drop (1+ n) syn)
                         (string-append result op-macro " ("
 ; Return C code to define the syntax string for SYNTAX
 ; MNEM is the C value to use to represent the instruction's mnemonic.
 ; OP is the C macro to use to compute an operand's syntax value.
+; ISA-NAME-LIST is the list of ISA names in which the owning insn lives.
 
-(define (gen-syntax-entry mnem op syntax)
+(define (gen-syntax-entry mnem op syntax isa-name-list)
   (string-append
    "{ { "
    mnem ", "
    ; `mnem' is used to represent the mnemonic, so we always want to strip it
    ; from the syntax string, regardless of the setting of `strip-mnemonic?'.
-   (compute-syntax #t #f syntax op)
+   (compute-syntax #t #f syntax op isa-name-list)
    " } }")
 )
 \f
     "/* " (insn-syntax insn) " */\n"
     "  {\n"
     "    " (gen-insn-handlers insn) ",\n"
-    "    " (gen-syntax-entry "MNEM" "OP" (insn-syntax insn)) ",\n"
+    "    "
+    (gen-syntax-entry "MNEM" "OP" (insn-syntax insn) (obj-isa-list insn))
+    ",\n"
     ; ??? 'twould save space to put a pointer here and record format separately
     "    " (gen-ifmt-entry insn) ", "
     ;"0x" (number->string (insn-value insn) 16) ",\n"
@@ -506,7 +510,9 @@ static unsigned int dis_hash_insn (const char *, CGEN_INSN_INT);
     "-1, " ; macro-insns are not currently enumerated, no current need to
     "\"" (obj:str-name minsn) "\", "
     "\"" (minsn-mnemonic minsn) "\",\n"
-    "    " (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn)) ",\n"
+    "    "
+    (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn) (obj-isa-list minsn))
+    ",\n"
     "    (PTR) & macro_" (gen-sym minsn) "_expansions[0],\n"
     "    "
     (gen-obj-attr-defn 'minsn minsn all-attrs num-non-bools gen-insn-attr-mask)
@@ -527,7 +533,9 @@ static unsigned int dis_hash_insn (const char *, CGEN_INSN_INT);
     "-1, " ; macro-insns are not currently enumerated, no current need to
     "\"" (obj:str-name minsn) "\", "
     "\"" (minsn-mnemonic minsn) "\",\n"
-    "    " (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn)) ",\n"
+    "    "
+    (gen-syntax-entry "MNEM" "OP" (minsn-syntax minsn) (obj-isa-list minsn))
+    ",\n"
     "    (PTR) & macro_" (gen-sym minsn) "_expansions[0],\n"
     "    "
     (gen-obj-attr-defn 'minsn minsn all-attrs num-non-bools gen-insn-attr-mask)
index c3bb859..6637b73 100644 (file)
                         (let ((expr (cadr encode))
                               (value (if (symbol? (caar encode)) (caar encode) (cadr (caar encode))))
                               (pc (if (symbol? (cadar encode)) (cadar encode) (cadr (cadar encode)))))
-                          (rtl-c DFLT expr
+                          (rtl-c DFLT
+                                 (obj-isa-list self)
                                  (list (list value (obj:name (ifld-decode-mode self)) "value")
-                                       (list pc 'IAI "pc"))))
+                                       (list pc 'IAI "pc"))
+                                 expr))
                         ";\n")
          "")
       (if need-extra?
                         (let ((expr (cadr decode))
                               (value (if (symbol? (caar decode)) (caar decode) (cadr (caar decode))))
                               (pc (if (symbol? (cadar decode)) (cadar decode) (cadr (cadar decode)))))
-                          (rtl-c DFLT expr
+                          (rtl-c DFLT
+                                 (obj-isa-list self)
                                  (list (list value (obj:name (ifld-decode-mode self)) "value")
-                                       (list pc 'IAI "pc"))))
+                                       (list pc 'IAI "pc"))
+                                 expr))
                         ";\n")
          "")
       (if need-extra?
                         (let ((expr (cadr encode))
                               (value (caar encode))
                               (pc (cadar encode)))
-                          (rtl-c DFLT expr
+                          (rtl-c DFLT
+                                 (obj-isa-list self)
                                  (list (list value (obj:name (ifld-decode-mode self)) varname)
-                                       (list pc 'IAI "pc"))))
+                                       (list pc 'IAI "pc"))
+                                 expr))
                         ";\n")
          "")
       (let ((expr (elm-get self 'insert)))
-       (rtl-c VOID expr nil))
+       (rtl-c VOID (obj-isa-list self) nil expr))
       (string-list-map (lambda (subfld)
                         (string-list
                          "  "
                          ))
                       (elm-get self 'subfields))
       (let ((expr (elm-get self 'extract)))
-       (rtl-c VOID expr nil))
+       (rtl-c VOID (obj-isa-list self) nil expr))
       (if need-extra?
          (string-append "        " varname " = "
                         (let ((expr (cadr decode))
                               (value (caar decode))
                               (pc (cadar decode)))
-                          (rtl-c DFLT expr
+                          (rtl-c DFLT
+                                 (obj-isa-list self)
                                  (list (list value (obj:name (ifld-decode-mode self)) varname)
-                                       (list pc 'IAI "pc"))))
+                                       (list pc 'IAI "pc"))
+                                 expr))
                         ";\n")
          "")
       "      }\n"
index 3467dd0..6a8713a 100644 (file)
   ;; 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_operand")))
+        (atlist-obj (atlist-parse context attrs "cgen_operand"))
+        (isa-name-list (atlist-attr-value atlist-obj 'ISA #f)))
+
+    ;; Verify all specified ISAs are valid.
+    (if (not (all-true? (map current-isa-lookup isa-name-list)))
+       (parse-error context "unknown isa in isa list" isa-name-list))
 
     (if (keep-atlist? atlist-obj #f)
 
              (mode-obj (parse-mode-name context mode))
              (ifld-val (if (integer? ifld)
                            ifld
-                           (current-ifld-lookup ifld))))
+                           (current-ifld-lookup ifld isa-name-list))))
 
          (if (not mode-obj)
              (parse-error context "unknown mode" mode))
 ; The result is a <derived-ifield> object.
 ; The {owner} member still needs to be set!
 
-(define (/derived-parse-encoding context operand-name encoding)
+(define (/derived-parse-encoding context isa-name-list operand-name encoding)
   (if (or (null? encoding)
          (not (list? encoding)))
       (parse-error context "encoding not a list" encoding))
 
   ; ??? Calling /parse-insn-format is a quick hack.
   ; It's an internal routine of some other file.
-  (let ((iflds (/parse-insn-format context #f #f encoding)))
+  (let ((iflds (/parse-insn-format context #f isa-name-list encoding)))
     (make <derived-ifield>
          operand-name
          'derived-ifield ; (string-append "<derived-ifield> for " operand-name)
 ;; asserting something about the ifield values of the containing insn.
 ;; The result is #f if the assertion is (), or the canonical rtl.
 
-(define (/derived-parse-ifield-assertion context ifield-assertion)
+(define (/derived-parse-ifield-assertion context isa-name-list ifield-assertion)
   (if (null? ifield-assertion)
       #f
-      (rtx-canonicalize context 'INT ifield-assertion nil))
+      (rtx-canonicalize context 'INT isa-name-list nil ifield-assertion))
 )
 
 ; Parse a derived operand definition.
   ;; 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_operand")))
+        (atlist-obj (atlist-parse context attrs "cgen_operand"))
+        (isa-name-list (atlist-attr-value atlist-obj 'ISA #f)))
+
+    ;; Verify all specified ISAs are valid.
+    (if (not (all-true? (map current-isa-lookup isa-name-list)))
+       (parse-error context "unknown isa in isa list" isa-name-list))
 
     (if (keep-atlist? atlist-obj #f)
 
-       (let ((mode-obj (parse-mode-name context mode))
-             (parsed-encoding (/derived-parse-encoding context name encoding)))
+       (let* ((mode-obj (parse-mode-name context mode))
+              (parsed-encoding (/derived-parse-encoding context isa-name-list
+                                                        name encoding)))
 
          (if (not mode-obj)
              (parse-error context "unknown mode" mode))
                       (map (lambda (a)
                              (if (not (symbol? a))
                                  (parse-error context "arg not a symbol" a))
-                             (let ((op (current-op-lookup a)))
+                             (let ((op (current-op-lookup a isa-name-list)))
                                (if (not op)
                                    (parse-error context "not an operand" a))
                                op))
                       syntax
                       base-ifield ; FIXME: validate
                       parsed-encoding
-                      (/derived-parse-ifield-assertion context ifield-assertion)
+                      (/derived-parse-ifield-assertion context isa-name-list
+                                                       ifield-assertion)
                       (if (null? getter)
                           #f
-                          (/operand-parse-getter context
-                                                 (list args
-                                                       (rtx-canonicalize context mode getter nil))
-                                                 (length args)))
+                          (/operand-parse-getter
+                           context
+                           (list args
+                                 (rtx-canonicalize context mode
+                                                   isa-name-list nil
+                                                   getter))
+                           (length args)))
                       (if (null? setter)
                           #f
-                          (/operand-parse-setter context
-                                                 (list (append args '(newval))
-                                                       (rtx-canonicalize context 'VOID setter
-                                                                         (list (list 'newval mode #f))))
-                                                 (length args)))
+                          (/operand-parse-setter
+                           context
+                           (list (append args '(newval))
+                                 (rtx-canonicalize context 'VOID
+                                                   isa-name-list
+                                                   (list (list 'newval mode #f))
+                                                   setter))
+                           (length args)))
                       )))
            (elm-set! result 'hw-name (obj:name (hardware-for-mode mode-obj)))
            ;(elm-set! result 'hw-name (obj:name parsed-encoding))
 ; Parse an "anyof" choice, which is a derived-operand name.
 ; The result is {choice} unchanged.
 
-(define (/anyof-parse-choice context choice)
+(define (/anyof-parse-choice context choice isa-name-list)
   (if (not (symbol? choice))
       (parse-error context "anyof choice not a symbol" choice))
-  (let ((op (current-op-lookup choice)))
+  (let ((op (current-op-lookup choice isa-name-list)))
     (if (not (derived-operand? op))
        (parse-error context "anyof choice not a derived-operand" choice))
     op)
 
     (if (keep-atlist? atlist-obj #f)
 
-       (let ((mode-obj (parse-mode-name context mode)))
+       (let ((mode-obj (parse-mode-name context mode))
+             (isa-name-list (atlist-attr-value atlist-obj 'ISA #f)))
          (if (not mode-obj)
              (parse-error context "unknown mode" mode))
 
                mode
                base-ifield
                (map (lambda (c)
-                      (/anyof-parse-choice context c))
+                      (/anyof-parse-choice context c isa-name-list))
                     choices)))
 
        (begin
   (assert (derived-operand? anyof-instance))
   (let ((assertion (derived-ifield-assertion anyof-instance)))
     (if assertion
-       (rtx-solve #f ; FIXME: context
+       (rtx-solve (make-obj-context anyof-instance #f)
                   anyof-instance ; owner
                   assertion
                   known-values)
   (elm-get anyof-instance 'name)
 )
 
-(define (/anyof-merge-syntax syntax value-names values)
-  (let ((syntax-elements (syntax-break-out syntax)))
+; CONTAINER is the <anyof-operand> containing SYNTAX.
+
+(define (/anyof-merge-syntax syntax value-names values container)
+  (let* ((isa-name-list (obj-isa-list container))
+        (syntax-elements (syntax-break-out syntax isa-name-list)))
     (syntax-make (map (lambda (e)
                        (if (anyof-operand? e)
                            (let* ((name (obj:name e))
                (op:mode choice)
                (derived-args choice)
                (/anyof-merge-syntax (derived-syntax choice)
-                                    arg-names new-args)
+                                    arg-names new-args
+                                    container)
                (derived-base-ifield choice)
                encoding
                (/anyof-merge-ifield-assertion (derived-ifield-assertion choice)
@@ -1616,6 +1639,7 @@ Define an anyof operand, name/value pair list version.
   ; Also (defined elsewhere): PCREL-ADDR ABS-ADDR.
 
   (set! pc (make <pc>))
+  (obj-cons-attr! pc (all-isas-attr))
   (current-op-add! pc)
 
   *UNSPECIFIED*
index f54ea62..25369c6 100644 (file)
 ; isa.
 
 (define (keep-isa? isa-list)
+  ;; If unspecified, the default is the first one in the list.
   (if (null? isa-list)
       (set! isa-list (list (car (current-arch-isa-name-list)))))
+
   (let* ((keep (reader-keep-isa CURRENT-READER))
         (keep? (map (lambda (i)
                       (or (memq i keep)
index 264fc4f..878f27a 100644 (file)
@@ -7,15 +7,16 @@
 ; ---------------------
 ; The main way to generate C code from an RTL expression is:
 ;
-; (rtl-c mode '(func mode ...) nil)
+; (rtl-c-parsed mode isa-name-list nil '(func mode ...))
 ;
 ; E.g.
-; (rtl-c SI '(add () SI (const () SI 1) (const () SI 2)) nil)
+; (rtl-c-parsed SI (all) nil '(add () SI (const () SI 1) (const () SI 2)))
 ; -->
 ; "ADDSI (1, 2)"
 ;
 ; The expression is in source form and must be already canonicalized (with
-; rtx-canonicalize).
+; rtx-canonicalize).  There is also rtl-c for the occasions where the rtl
+; isn't already canonicalized.
 ;
 ; The `set' rtx needs to be handled a little carefully.
 ; Both the dest and src are processed first, and then code to perform the
 )
 
 ;; Build an estate for use in generating C.
-;; EXTRA-VARS-ALIST is an association list of
-;; (symbol <mode>-or-mode-name value) elements to be used during value lookup.
 ;; OVERRIDES is a #:keyword/value list of parameters to apply last.
-;;
-;; ??? Move EXTRA-VARS-ALIST into OVERRIDES (caller would have to call
-;; rtx-env-init-stack1)?
 
-(define (estate-make-for-rtl-c extra-vars-alist overrides)
+(define (estate-make-for-rtl-c overrides)
   (apply vmake
         (append!
          (list
           <rtl-c-eval-state>
           #:expr-fn (lambda (rtx-obj expr mode estate)
                       (rtl-c-generator rtx-obj))
-          #:env (rtx-env-init-stack1 extra-vars-alist)
           #:rtl-cover-fns? /rtl-c-rtl-cover-fns?)
          overrides))
 )
 )
 
 ; Translate parsed RTL expression X to a string of C code.
-; X must have already been fed through rtx-canonicalize.
+; EXPR must have already been fed through rtx-canonicalize.
 ; MODE is the desired mode of the value or DFLT for "natural mode".
 ; MODE is a <mode> object.
-; EXTRA-VARS-ALIST is an association list of extra
-; (symbol <mode>-or-mode-name value) elements to be used during value lookup.
 ; OVERRIDES is a #:keyword/value list of arguments to build the eval state
 ; with.
 
-(define (rtl-c-parsed mode x extra-vars-alist . overrides)
+(define (rtl-c-parsed mode expr . overrides)
   ;; ??? If we're passed insn-compiled-semantics the output of xops is
   ;; confusing.  Fix by subclassing <operand> -> <xoperand>, and
   ;; have <xoperand> provide original source expr.
-  (let ((estate (estate-make-for-rtl-c extra-vars-alist
-                                      (cons #:outer-expr
-                                            (cons x overrides)))))
-    (rtl-c-with-estate estate mode x))
+  (let ((estate (estate-make-for-rtl-c (cons #:outer-expr
+                                            (cons expr overrides)))))
+    (rtl-c-with-estate estate mode expr))
 )
 
-; Same as rtl-c-parsed but X is unparsed.
+; Same as rtl-c-parsed but EXPR is unparsed.
+; ISA-NAME-LIST is the list of ISA(s) in which to evaluate EXPR.
+; EXTRA-VARS-ALIST is an association list of extra (symbol <mode> value)
+; elements to be used during value lookup.
 ; MODE is a <mode> object.
 
-(define (rtl-c mode x extra-vars-alist . overrides)
-  ;; This doesn't pass the canonicalized expr for #outer-expr on purpose,
-  ;; to keep it closer to what the user wrote.
-  (let ((estate (estate-make-for-rtl-c extra-vars-alist
-                                      (cons #:outer-expr
-                                            (cons x overrides)))))
-    (rtl-c-with-estate estate mode (rtx-canonicalize #f (obj:name mode) x
-                                                    extra-vars-alist)))
+(define (rtl-c mode isa-name-list extra-vars-alist expr . overrides)
+  (let* ((canonical-rtl (rtx-canonicalize #f (obj:name mode)
+                                         isa-name-list extra-vars-alist expr))
+        (estate (estate-make-for-rtl-c (cons #:outer-expr
+                                             (cons canonical-rtl overrides)))))
+    (rtl-c-with-estate estate mode canonical-rtl))
 )
 
 ; Same as rtl-c-with-estate except return a <c-expr> object.
 ; Same as rtl-c-parsed except return a <c-expr> object.
 ; MODE is a <mode> object.
 
-(define (rtl-c-expr-parsed mode x extra-vars-alist . overrides)
+(define (rtl-c-expr-parsed mode expr . overrides)
   ;; ??? If we're passed insn-compiled-semantics the output of xops is
   ;; confusing.  Fix by subclassing <operand> -> <xoperand>, and
   ;; have <xoperand> provide original source expr.
-  (let ((estate (estate-make-for-rtl-c extra-vars-alist
-                                      (cons #:outer-expr
-                                            (cons x overrides)))))
-    (rtl-c-expr-with-estate estate mode x))
+  (let ((estate (estate-make-for-rtl-c (cons #:outer-expr
+                                            (cons expr overrides)))))
+    (rtl-c-expr-with-estate estate mode expr))
 )
 
-; Same as rtl-c-expr-parsed but X is unparsed.
+; Same as rtl-c-expr-parsed but EXPR is unparsed.
 ; MODE is a <mode> object.
 
-(define (rtl-c-expr mode x extra-vars-alist . overrides)
-  ;; This doesn't pass the canonicalized expr for #outer-expr on purpose,
-  ;; to keep it closer to what the user wrote.
-  (let ((estate (estate-make-for-rtl-c extra-vars-alist
-                                      (cons #:outer-expr
-                                            (cons x overrides)))))
-    (rtl-c-expr-with-estate estate mode (rtx-canonicalize #f (obj:name mode) x
-                                                         extra-vars-alist)))
+(define (rtl-c-expr mode isa-name-list extra-vars-alist expr . overrides)
+  (let* ((canonical-rtl (rtx-canonicalize #f (obj:name mode)
+                                         isa-name-list extra-vars-alist expr))
+        (estate (estate-make-for-rtl-c (cons #:outer-expr
+                                             (cons canonical-rtl overrides)))))
+    (rtl-c-expr-with-estate estate mode canonical-rtl))
 )
 \f
 ; C++ versions of rtl-c routines.
 
 ; Build an estate for use in generating C++.
-; EXTRA-VARS-ALIST is an association list of (symbol <mode> value)
-; elements to be used during value lookup.
 ; OVERRIDES is a #:keyword/value list of parameters to apply last.
 
-(define (estate-make-for-rtl-c++ extra-vars-alist overrides)
-  (estate-make-for-rtl-c extra-vars-alist
-                        (cons #:output-language (cons "c++" overrides)))
+(define (estate-make-for-rtl-c++ overrides)
+  (estate-make-for-rtl-c (cons #:output-language (cons "c++" overrides)))
 )
 
 ; Translate parsed RTL expression X to a string of C++ code.
-; X must have already been fed through rtx-canonicalize.
+; EXPR must have already been fed through rtx-canonicalize.
 ; MODE is the desired mode of the value or DFLT for "natural mode".
 ; MODE is a <mode> object.
-; EXTRA-VARS-ALIST is an association list of extra (symbol <mode> value)
-; elements to be used during value lookup.
 ; OVERRIDES is a #:keyword/value list of arguments to build the eval state
 ; with.
 
-(define (rtl-c++-parsed mode x extra-vars-alist . overrides)
+(define (rtl-c++-parsed mode expr . overrides)
   ;; ??? If we're passed insn-compiled-semantics the output of xops is
   ;; confusing.  Fix by subclassing <operand> -> <xoperand>, and
   ;; have <xoperand> provide original source expr.
-  (let ((estate (estate-make-for-rtl-c++ extra-vars-alist
-                                        (cons #:outer-expr
-                                              (cons x overrides)))))
-    (rtl-c-with-estate estate mode x))
+  (let ((estate (estate-make-for-rtl-c++ (cons #:outer-expr
+                                              (cons expr overrides)))))
+    (rtl-c-with-estate estate mode expr))
 )
 
-; Same as rtl-c++-parsed but X is unparsed.
+; Same as rtl-c++-parsed but EXPR is unparsed.
 ; MODE is a <mode> object.
 
-(define (rtl-c++ mode x extra-vars-alist . overrides)
-  ;; This doesn't pass the canonicalized expr for #outer-expr on purpose,
-  ;; to keep it closer to what the user wrote.
-  (let ((estate (estate-make-for-rtl-c++ extra-vars-alist
-                                        (cons #:outer-expr
-                                              (cons x overrides)))))
-    (rtl-c-with-estate estate mode (rtx-canonicalize #f (obj:name mode) x
-                                                    extra-vars-alist)))
+(define (rtl-c++ mode isa-name-list extra-vars-alist expr . overrides)
+  (let* ((canonical-rtl (rtx-canonicalize #f (obj:name mode)
+                                         isa-name-list extra-vars-alist expr))
+        (estate (estate-make-for-rtl-c++ (cons #:outer-expr
+                                               (cons canonical-rtl overrides)))))
+    (rtl-c-with-estate estate mode canonical-rtl))
 )
 \f
 ; Top level routines for getting/setting values.
                     (obj:name mode))))))
 
          ;; FIXME: Can we ever get a symbol here?
-         ((or (and (symbol? src) (rtx-temp-lookup (estate-env estate) src))
+         ((or (and (symbol? src) (rtx-temp-lookup (estate-env-stack estate) src))
               (rtx-temp? src))
           (begin
             (if (symbol? src)
-                (set! src (rtx-temp-lookup (estate-env estate) src)))
+                (set! src (rtx-temp-lookup (estate-env-stack estate) src)))
             (cond ((mode:eq? 'DFLT mode)
                    (send src 'cxmake-get estate (rtx-temp-mode src) #f #f))
                   ((rtx-mode-compatible? mode (rtx-temp-mode src))
   (let* ((limit-var (rtx-make-iteration-limit-var iter-var))
         (env (rtx-env-make-iteration-locals iter-var))
         (estate (estate-push-env estate env))
-        (temp-iter (rtx-temp-lookup (estate-env estate) iter-var))
-        (temp-limit (rtx-temp-lookup (estate-env estate) limit-var))
+        (temp-iter (rtx-temp-lookup (estate-env-stack estate) iter-var))
+        (temp-limit (rtx-temp-lookup (estate-env-stack estate) limit-var))
         (c-iter-var (rtx-temp-value temp-iter))
         (c-limit-var (rtx-temp-value temp-limit)))
     (cx:make VOID
   (cond ((rtx-temp? object-or-name)
         object-or-name)
        ((symbol? object-or-name)
-        (let ((object (rtx-temp-lookup (estate-env *estate*) object-or-name)))
+        (let ((object (rtx-temp-lookup (estate-env-stack *estate*) object-or-name)))
           (if (not object)
               (estate-error *estate* "undefined local" object-or-name))
           object))
         (cons *estate* (cons iter-var (cons nr-times (cons expr exprs)))))
 )
 
-(define-fn closure (*estate* options mode expr env)
-  ; ??? estate-push-env?
-  (rtl-c-with-estate (estate-new-env *estate* env) (mode:lookup mode) expr)
+(define-fn closure (*estate* options mode isa-name-list env-stack expr)
+  (rtl-c-with-estate (estate-make-closure *estate* isa-name-list
+                                         (rtx-make-env-stack env-stack))
+                    (mode:lookup mode) expr)
 )
 \f
 ;; The result is the rtl->c generator table.
index 807d295..89c502f 100644 (file)
 ;; This carries the immutable elements only!
 ;; OUTER-EXPR is the EXPR argument to rtx-canonicalize.
 
-(define (/make-cstate context outer-expr)
-  (vector context outer-expr)
+(define (/make-cstate context isa-name-list outer-expr)
+  (vector context isa-name-list outer-expr)
 )
 
 (define (/cstate-context cstate) (vector-ref cstate 0))
-(define (/cstate-outer-expr cstate) (vector-ref cstate 1))
+(define (/cstate-isas cstate) (vector-ref cstate 1))
+(define (/cstate-outer-expr cstate) (vector-ref cstate 2))
 
 ;; Flag an error while canonicalizing rtl.
 
     (cons val (cons new-env env)))
 )
 
-(define (/rtx-canon-env val mode parent-expr op-num cstate env depth)
+(define (/rtx-canon-symbol-list val mode parent-expr op-num cstate env depth)
+  (if (or (not (list? val))
+         (not (all-true? (map symbol? val))))
+      (/rtx-canon-error cstate "bad symbol list"
+                       val parent-expr op-num))
+  #f
+)
+
+(define (/rtx-canon-env-stack val mode parent-expr op-num cstate env depth)
   ;; VAL is an environment stack.
   (if (not (list? val))
       (/rtx-canon-error cstate "environment not a list"
          (cons 'CASERTX /rtx-canon-casertx)
          (cons 'LOCALS /rtx-canon-locals)
          (cons 'ITERATION /rtx-canon-iteration)
-         (cons 'ENV /rtx-canon-env)
+         (cons 'SYMBOLLIST /rtx-canon-symbol-list)
+         (cons 'ENVSTACK /rtx-canon-env-stack)
          (cons 'ATTRS /rtx-canon-attrs)
          (cons 'SYMBOL /rtx-canon-symbol)
          (cons 'STRING /rtx-canon-string)
 
   (let ((expr-mode-name (cadr args))
        (op-name (caddr args)))
-    (let ((op-obj (current-op-lookup op-name)))
+    (let ((op-obj (current-op-lookup op-name (/cstate-isas cstate))))
 
       (if op-obj
 
   (let ((expr-mode-name (cadr args))
        (ref-name (caddr args)))
     ;; FIXME: Will current-op-lookup find named operands?
-    (let ((op-obj (current-op-lookup env ref-name)))
+    (let ((op-obj (current-op-lookup ref-name (/cstate-isas cstate))))
 
       (if op-obj
 
          (display requested-mode-name)
          (newline)
          (display (spaces (* 4 depth)))
-         (rtx-env-dump env)
+         (rtx-env-stack-dump env)
          (force-output)))
 
     (let* ((canoner (vector-ref /rtx-operand-canoners (rtx-num rtx-obj)))
        (display (rtx-dump expr))
        (newline)
        (display (spaces (* 4 depth)))
-       (rtx-env-dump env)
+       (rtx-env-stack-dump env)
        (force-output)
        ))
 
             (if (memq expected '(RTX SETRTX))
 
                 (cond ((symbol? expr)
-                       (cond ((current-op-lookup expr)
+                       (cond ((current-op-lookup expr (/cstate-isas cstate))
                               => (lambda (op)
                                    ;; NOTE: We can't simply call
                                    ;; op:mode-name here, we need the real
 ;;   - ifield-name -> (ifield ifield-name)
 ;; Plus an absent option list is replaced with ().
 ;; Plus DFLT mode is converted to a useful mode.
+;; Plus the specified isa-name-list is recorded in the RTL.
 ;;
 ;; The result is EXPR in canonical form.
 ;;
 ;; CONTEXT is a <context> object or #f if there is none.
 ;; It is used in error messages.
 ;;
+;; ISA-NAME-LIST is a list of ISAs in which to evaluate the expression,
+;; e.g. to do operand lookups.
+;; The ISAs must be compatible, e.g. operand lookups must be unambiguous.
+;;
 ;; MODE-NAME is the requested mode of the result, or DFLT.
 ;;
 ;; EXTRA-VARS-ALIST is an association list of extra (symbol <mode> value)
 ;; elements to be used during value lookup.
-;; VALUE can be #f which means "unknown".
-;;
-;; ??? If EXTRA-VARS-ALIST is non-null, it might be nice to return a closure.
-;; It might simplify subsequent uses of the canonicalized code.
-
-(define (rtx-canonicalize context mode-name expr extra-vars-alist)
+;; VALUE can be #f which means the value is assumed to be known, but is
+;; currently unrepresentable.  This is used, for example, when representing
+;; ifield setters: we don't know the new value, but it will be known when the
+;; rtx is evaluated (??? Sigh, this is a bit of a cheat, closures have no
+;; such thing, but it's useful here because we don't necessarily know what
+;; the value will be in the application side of things).
+
+(define (rtx-canonicalize context mode-name isa-name-list extra-vars-alist expr)
   (let ((result
         (/rtx-canon expr 'RTX mode-name #f 0
-                    (/make-cstate context expr)
+                    (/make-cstate context isa-name-list expr)
                     (rtx-env-init-stack1 extra-vars-alist) 0)))
     (rtx-verify-no-dflt-modes context result)
-    result)
-)
-
-;; Utility for a common case.
-;; Canonicalize rtl expression STMT which has a VOID result,
-;; and no external environment.
-
-(define (rtx-canonicalize-stmt context stmt)
-  (rtx-canonicalize context 'VOID stmt nil)
+    (rtx-make 'closure mode-name isa-name-list
+             (rtx-var-alist-to-closure-env-stack extra-vars-alist)
+             result))
 )
 \f
 ;; RTL expression traversal support.
 ; computing the insn format) EXPR-FN processes the expression itself, and
 ; when evaluating EXPR it's the result of EXPR-FN that computes the value.
 ;
+; ISAS is a list of ISA name(s) in which to evaluate the expression.
+;
 ; ENV is the current environment.  This is a stack of sequence locals.
 ;
 ; COND? is a boolean indicating if the current expression is on a conditional
 ;
 ; DEPTH is the current traversal depth.
 
-(define (tstate-make context owner expr-fn env cond? known depth)
-  (vector context owner expr-fn env cond? known depth)
-)
-
-(define (tstate-context state)             (vector-ref state 0))
-(define (tstate-set-context! state newval) (vector-set! state 0 newval))
-(define (tstate-owner state)               (vector-ref state 1))
-(define (tstate-set-owner! state newval)   (vector-set! state 1 newval))
-(define (tstate-expr-fn state)             (vector-ref state 2))
-(define (tstate-set-expr-fn! state newval) (vector-set! state 2 newval))
-(define (tstate-env state)                 (vector-ref state 3))
-(define (tstate-set-env! state newval)     (vector-set! state 3 newval))
-(define (tstate-cond? state)               (vector-ref state 4))
-(define (tstate-set-cond?! state newval)   (vector-set! state 4 newval))
-(define (tstate-known state)               (vector-ref state 5))
-(define (tstate-set-known! state newval)   (vector-set! state 5 newval))
-(define (tstate-depth state)               (vector-ref state 6))
-(define (tstate-set-depth! state newval)   (vector-set! state 6 newval))
+(define (tstate-make context owner expr-fn isas env cond? known depth)
+  (vector context owner expr-fn isas env cond? known depth)
+)
+
+(define (tstate-context state)               (vector-ref state 0))
+(define (tstate-set-context! state newval)   (vector-set! state 0 newval))
+(define (tstate-owner state)                 (vector-ref state 1))
+(define (tstate-set-owner! state newval)     (vector-set! state 1 newval))
+(define (tstate-expr-fn state)               (vector-ref state 2))
+(define (tstate-set-expr-fn! state newval)   (vector-set! state 2 newval))
+(define (tstate-isas state)                  (vector-ref state 3))
+(define (tstate-set-isas! state newval)      (vector-set! state 3 newval))
+(define (tstate-env-stack state)             (vector-ref state 4))
+(define (tstate-set-env-stack! state newval) (vector-set! state 4 newval))
+(define (tstate-cond? state)                 (vector-ref state 5))
+(define (tstate-set-cond?! state newval)     (vector-set! state 5 newval))
+(define (tstate-known state)                 (vector-ref state 6))
+(define (tstate-set-known! state newval)     (vector-set! state 6 newval))
+(define (tstate-depth state)                 (vector-ref state 7))
+(define (tstate-set-depth! state newval)     (vector-set! state 7 newval))
 
 ; Create a copy of STATE.
 
   (list->vector (vector->list state))
 )
 
-; Create a copy of STATE with a new environment ENV.
+;; Create a copy of STATE with environment stack ENV-STACK added,
+;; and the ISA(s) set to ISA-NAME-LIST.
 
-(define (tstate-new-env state env)
+(define (tstate-make-closure state isa-name-list env-stack)
   (let ((result (tstate-copy state)))
-    (tstate-set-env! result env)
+    (tstate-set-isas! result isa-name-list)
+    (tstate-set-env-stack! result (append env-stack (tstate-env-stack result)))
     result)
 )
 
 
 (define (tstate-push-env state env)
   (let ((result (tstate-copy state)))
-    (tstate-set-env! result (cons env (tstate-env result)))
+    (tstate-set-env-stack! result (cons env (tstate-env-stack result)))
     result)
 )
 
     (cons val (tstate-push-env tstate env)))
 )
 
-(define (/rtx-traverse-env val expr op-num tstate appstuff)
-  ;; VAL is an environment stack.
-  (cons val (tstate-new-env tstate val))
-)
-
 (define (/rtx-traverse-attrs val expr op-num tstate appstuff)
 ;  (cons val ; (atlist-source-form (atlist-parse (make-prefix-context "with-attr") val ""))
 ;      tstate)
          (cons 'CASERTX /rtx-traverse-casertx)
          (cons 'LOCALS /rtx-traverse-locals)
          (cons 'ITERATION /rtx-traverse-iteration)
-         (cons 'ENV /rtx-traverse-env)
+         ;; NOTE: Closure isas and env are handled in /rtx-traverse.
+         (cons 'SYMBOLLIST /rtx-traverse-normal-operand)
+         (cons 'ENVSTACK /rtx-traverse-normal-operand)
          (cons 'ATTRS /rtx-traverse-attrs)
          (cons 'SYMBOL /rtx-traverse-normal-operand)
          (cons 'STRING /rtx-traverse-normal-operand)
        (display "Traversing operands of: ")
        (display (rtx-dump expr))
        (newline)
-       (rtx-env-dump (tstate-env tstate))
+       (rtx-env-stack-dump (tstate-env-stack tstate))
        (force-output)))
 
   (let loop ((operands (cdr expr))
 ; TSTATE is the current traversal state.
 ;
 ; APPSTUFF is for application specific use.
-;
-; All macros are expanded here.  User code never sees them.
-; All operand shortcuts are also expand here.  User code never sees them.
-; These are:
-; - operands, ifields, and numbers appearing where an rtx is expected are
-;   converted to use `operand', `ifield', or `const'.
 
 (define (/rtx-traverse expr expected parent-expr op-pos tstate appstuff)
   (if /rtx-traverse-debug?
        (display "-expected:       ")
        (display expected)
        (newline)
+       (display (spaces (* 4 (tstate-depth tstate))))
+       (display "-conditional:    ")
+       (display (tstate-cond? tstate))
+       (newline)
        (force-output)
        ))
 
 
   (if (pair? expr) ; pair? -> cheap non-null-list?
 
-      (let ((rtx-obj (rtx-lookup (car expr))))
+      (let* ((rtx-name (car expr))
+            (rtx-obj (rtx-lookup rtx-name))
+            ;; If this is a closure, update tstate.
+            ;; ??? This is a bit of a wart.  All other rtxes handle their
+            ;; special args/needs via rtx-arg-types.  Left as is to simmer.
+            (tstate (if (eq? rtx-name 'closure)
+                        (tstate-make-closure tstate
+                                             (rtx-closure-isas expr)
+                                             (rtx-make-env-stack (rtx-closure-env-stack expr)))
+                        tstate)))
        (tstate-incr-depth! tstate)
        (let ((result
               (if rtx-obj
                   (/rtx-traverse-expr rtx-obj expr parent-expr op-pos tstate appstuff)
-                  (let ((rtx-obj (/rtx-macro-lookup (car expr))))
+                  (let ((rtx-obj (/rtx-macro-lookup rtx-name)))
                     (if rtx-obj
                         (/rtx-traverse (/rtx-macro-expand expr rtx-evaluator)
                                        expected parent-expr op-pos tstate appstuff)
 
       ; EXPR is not a list.
       ; See if it's an operand shortcut.
+      ; FIXME: Can we get here any more? [now that EXPR is already canonical]
       (if (memq expected '(RTX SETRTX))
 
          (cond ((symbol? expr)
-                (cond ((current-op-lookup expr)
+                (cond ((current-op-lookup expr (tstate-isas tstate))
                        => (lambda (op)
                             (/rtx-traverse
                              ;; NOTE: Can't call op:mode-name here, we need
                              ;; the real mode, not (potentially) DFLT.
                              (rtx-make-operand (obj:name (op:mode op)) expr)
                              expected parent-expr op-pos tstate appstuff)))
-                      ((rtx-temp-lookup (tstate-env tstate) expr)
+                      ((rtx-temp-lookup (tstate-env-stack tstate) expr)
                        => (lambda (tmp)
                             (/rtx-traverse
                              (rtx-make-local (rtx-temp-mode tmp) expr)
 )
 
 ; User visible procedures to traverse an rtl expression.
-; EXPR must be fully canonical (i.e. compiled).
+; EXPR must be fully canonical.
 ; These calls /rtx-traverse to do most of the work.
 ; See tstate-make for explanations of OWNER, EXPR-FN.
 ; CONTEXT is a <context> object or #f if there is none.
 
 (define (rtx-traverse context owner expr expr-fn appstuff)
   (/rtx-traverse expr #f #f 0
-                (tstate-make context owner expr-fn (rtx-env-empty-stack)
+                (tstate-make context owner expr-fn
+                             #f ;; ok since EXPR is fully canonical
+                             (rtx-env-empty-stack)
                              #f nil 0)
                 appstuff)
 )
 (define (rtx-traverse-with-locals context owner expr expr-fn locals appstuff)
   (/rtx-traverse expr #f #f 0
                 (tstate-make context owner expr-fn
+                             #f ;; ok since EXPR is fully canonical
                              (rtx-env-push (rtx-env-empty-stack)
                                            (rtx-env-make-locals locals))
                              #f nil 0)
                ; In time things should be simplified.
                (expr-fn . #f)
 
-               ; Current environment.  This is a stack of sequence locals.
-               (env . ())
+               ; List of ISA name(s) in which to evaluate the expression.
+               ; This is used for example during operand lookups.
+               ; All specified ISAs must be compatible,
+               ; e.g. operand lookups must be unambiguous.
+               ; A value of #f means "all ISAs".
+               (isas . #f)
+
+               ; Current environment.  This is a stack of sequence locals,
+               ; e.g. made with rtx-env-init-stack1.
+               (env-stack . ())
 
                ; Current evaluation depth.  This is used, for example, to
                ; control indentation in generated output.
              (elm-set! self 'outer-expr (cadr args)))
             ((#:expr-fn)
              (elm-set! self 'expr-fn (cadr args)))
-            ((#:env)
-             (elm-set! self 'env (cadr args)))
+            ((#:env-stack)
+             (elm-set! self 'env-stack (cadr args)))
+            ((#:isas)
+             (elm-set! self 'isas (cadr args)))
             ((#:depth)
              (elm-set! self 'depth (cadr args)))
             ((#:modifiers)
 ; Accessors.
 
 (define-getters <eval-state> estate
-  (context owner outer-expr expr-fn env depth modifiers)
+  (context owner outer-expr expr-fn isas env-stack depth modifiers)
 )
 (define-setters <eval-state> estate
-  (env depth modifiers)
+  (isas env-stack depth modifiers)
 )
 
 ; Build an estate for use in producing a value from rtl.
         #:context context
         #:owner owner
         #:expr-fn (lambda (rtx-obj expr mode estate)
-                    (rtx-evaluator rtx-obj)))
+                    (rtx-evaluator rtx-obj))
+        #:isas (and owner (obj-isa-list owner)))
 )
 
 ; Create a copy of ESTATE.
   (object-copy-top estate)
 )
 
-; Create a copy of ESTATE with a new environment ENV.
+;; Create a copy of ESTATE with environment stack ENV-STACK added,
+;; and the ISA(s) set to ISA-NAME-LIST.
 
-(define (estate-new-env estate env)
+(define (estate-make-closure estate isa-name-list env-stack)
   (let ((result (estate-copy estate)))
-    (estate-set-env! result env)
+    (estate-set-isas! result isa-name-list)
+    (estate-set-env-stack! result (append env-stack (estate-env-stack result)))
     result)
 )
 
 
 (define (estate-push-env estate env)
   (let ((result (estate-copy estate)))
-    (estate-set-env! result (cons env (estate-env result)))
+    (estate-set-env-stack! result (cons env (estate-env-stack result)))
     result)
 )
 
 (define (tstate->estate t)
   (vmake <eval-state>
         #:context (tstate-context t)
-        #:env (tstate-env t))
+        #:env-stack (tstate-env-stack t))
 )
 
 ; Issue an error given an estate.
        (newline)
        (display (rtx-dump expr))
        (newline)
-       (rtx-env-dump (estate-env estate))
+       (rtx-env-stack-dump (estate-env-stack estate))
        ))
 
   (if (pair? expr) ; pair? -> cheap non-null-list?
 
 ; Evaluate rtx expression EXPR and return the computed value.
 ; EXPR must already be in canonical form (the result of rtx-canonicalize).
-; OWNER is the owner of the value, used for attribute computation,
-; or #f if there isn't one.
+; OWNER is the owner of the value, used for attribute computation
+; and to get the ISA name list.
+; OWNER is #f if there isn't one.
 ; FIXME: context?
 
 (define (rtx-value expr owner)
index 1f7d939..1ff896e 100644 (file)
           known-val ; (rtx-make 'const 'INT known-val)
           #f)))
 
+    ((closure)
+     (let ((simplified-expr (/rtx-traverse (rtx-closure-expr expr)
+                                          'RTX expr 2 tstate appstuff)))
+       simplified-expr))
+
     ; Leave EXPR unchanged and continue.
     (else #f))
 )
   (/rtx-traverse expr #f #f 0
                 (tstate-make context owner
                              /rtx-simplify-expr-fn
+                             #f ;; ok since EXPR is fully canonical
                              (rtx-env-empty-stack)
                              #f known 0)
                 #f)
 ;        (/rtx-traverse simplified-expr #f #f 0
 ;                       (tstate-make context owner
 ;                                    /solve-expr-fn
-;                                    (rtx-env-empty-stack)
+;                                    #f (rtx-env-empty-stack)
 ;                                    #f known 0)
 ;                       #f))
         )
              ((LOCALS)
               #f) ; leave arg untouched
 
-             ((ENV)
+             ((ITERATION SYMBOLLIST ENVSTACK)
               #f) ; leave arg untouched for now
 
              ((ATTRS)
 
 (define (/rtx-trim-for-doc rtx)
   (if (pair? rtx) ; ??? cheap rtx?
+
       (let ((name (car rtx))
            (options (cadr rtx))
            (mode (caddr rtx))
                     (cons name (cons mode (reverse result))))
                 (cons name (cons options (cons mode (reverse result)))))))
 
+         ((closure)
+          ;; Remove outer closures, they are artificially added, and are
+          ;; basically noise to the human trying to understand the semantics.
+          ;; ??? Since we currently can't distinguish outer closures,
+          ;; just remove them all.
+          (let ((trimmed-expr (/rtx-trim-for-doc (rtx-closure-expr rtx))))
+            (if (and (null? options) (null? (rtx-closure-env-stack rtx)))
+                trimmed-expr
+                (rtx-make 'closure options mode
+                          (rtx-closure-isas rtx)
+                          (rtx-closure-env-stack rtx)
+                          trimmed-expr))))
+
          (else
           (let ((trimmed-args (/rtx-trim-args name rest)))
             (if (null? options)
index 9f3a178..6173456 100644 (file)
@@ -66,7 +66,8 @@
                ; CASERTX - a case expression ((symbol .. symbol) rtx ... rtx)
                ; LOCALS - the locals list of a sequence
                ; ITERATION - the iteration 
-               ; ENV - environment stack
+               ; SYMBOLLIST - used for ISA name lists
+               ; ENVSTACK - environment stack
                ; ATTRS - attribute list
                ; SYMBOL - arg must be a symbol
                ; STRING - arg must be a string
    '(OPTIONS)
     /rtx-valid-mode-types
     '(RTX SETRTX TESTRTX CONDRTX CASERTX)
-    '(LOCALS ENV ATTRS SYMBOL STRING NUMBER SYMORNUM OBJECT)
+    '(LOCALS ITERATION SYMBOLLIST ENVSTACK ATTRS)
+    '(SYMBOL STRING NUMBER SYMORNUM OBJECT)
     )
 )
 
 (define (rtx-lvalue-mode-name estate x)
   (assert (rtx? x))
   (case (car x)
-;    ((operand) (obj:name (op:mode (current-op-lookup (cadr x)))))
+;    ((operand) (obj:name (op:mode (current-op-lookup (cadr x) (obj-isa-list (estate-owner estate))))))
     ((xop) (obj:name (send (rtx-xop-obj x) 'get-mode)))
 ;    ((opspec)
 ;     (if (eq? (rtx-opspec-mode x) 'VOID)
 ;    ((reg mem) (cadr x))
     ((local) ;; (local options mode name)
      (let* ((name (cadddr x))
-           (temp (rtx-temp-lookup (estate-env estate) name)))
+           (temp (rtx-temp-lookup (estate-env-stack estate) name)))
        (if (not temp)
           (estate-error estate "unknown local" name))
        (obj:name (rtx-temp-mode temp))))
 
 (define (rtx-env-stack-empty? env-stack) (null? env-stack))
 (define (rtx-env-stack-head env-stack) (car env-stack))
-(define (rtx-env-var-list env) env)
 (define (rtx-env-empty-stack) nil)
 (define (rtx-env-init-stack1 vars-alist)
   (if (null? vars-alist)
 )
 (define (rtx-env-empty? env) (null? env))
 
-; Create an initial environment.
-; VAR-LIST is a list of (name <mode>-or-mode-name value) elements.
-
-(define (rtx-env-make var-list)
-  ; Convert VAR-LIST to an associative list of <rtx-temp> objects.
-  (map (lambda (var-spec)
-        (cons (car var-spec)
-              (make <rtx-temp>
-                (car var-spec)
-                (mode-maybe-lookup (cadr var-spec))
-                (caddr var-spec))))
-       var-list)
+;; Create an environment from VAR-ALIST,
+;; an alist of (name <mode>-or-mode-name value) elements,
+;; or, in the case of /rtx-closure-make, a list of (name . <rtx-temp>).
+
+(define (rtx-env-make var-alist)
+  ;; Check for an already-compiled environment, for /rtx-closure-make's sake.
+  (if (and (pair? var-alist)
+          (rtx-temp? (cdar var-alist)))
+      var-alist
+      ;; Convert VAR-ALIST to an associative list of <rtx-temp> objects.
+      (map (lambda (var-spec)
+            (cons (car var-spec)
+                  (make <rtx-temp>
+                    (car var-spec)
+                    (mode-maybe-lookup (cadr var-spec))
+                    (caddr var-spec))))
+          var-alist))
 )
 
 ; Create an initial environment with local variables.
                             (list 'INT (rtx-make-iteration-limit-var iter-var))))
 )
 
+;; Convert an alist of (name <mode>-object-or-name value) to
+;; an environment.
+
+(define (rtx-var-alist-to-env var-alist) var-alist)
+
+;; Convert an alist of (name <mode>-object-or-name value) to
+;; an environment stack.
+
+(define (rtx-var-alist-to-closure-env-stack var-alist)
+  ;; Preserve emptiness so (null? env-stack) works.
+  (if (null? var-alist)
+      nil
+      (list var-alist))
+)
+
+;; Convert the source form of an env-stack, e.g. as used in a closure,
+;; to the internal form, which is (name <rtx-temp>-object).
+
+(define (rtx-make-env-stack closure-env-stack)
+  (map rtx-env-make closure-env-stack)
+)
+
 ; Push environment ENV onto the front of environment stack ENV-STACK,
 ; returning a new object.  ENV-STACK is not modified.
 
   (cons env env-stack)
 )
 
-; Lookup variable NAME in environment ENV.
+; Lookup variable NAME in environment stack ENV-STACK.
 ; The result is the <rtx-temp> object.
-; ??? Should environments only have rtx-temps?
 
-(define (rtx-temp-lookup env name)
-  (let loop ((stack (rtx-env-var-list env)))
+(define (rtx-temp-lookup env-stack name)
+  (let loop ((stack env-stack))
     (if (null? stack)
        #f
        (let ((temp (assq-ref (car stack) name)))
              (loop (cdr stack))))))
 )
 
-; Create a "closure" of EXPR using the current temp stack.
+; Create a "closure" of EXPR using the current ISA list and temp stack.
+; MODE is the mode name.
 
 (define (/rtx-closure-make estate mode expr)
-  (rtx-make 'closure mode expr (estate-env estate))
+  ;; NOTE: This records the "compiled" environment stack in the closure.
+  (rtx-make 'closure mode (estate-isas estate) (estate-env-stack estate)
+           expr)
 )
 
-(define (rtx-env-dump env)
-  (let ((stack env))
+(define (rtx-env-stack-dump env-stack)
+  (let ((stack env-stack))
     (if (rtx-env-stack-empty? stack)
        (display "rtx-env stack (empty):\n")
        (let loop ((stack stack) (level 0))
 (define (rtx-ifield-obj rtx)
   (let ((ifield (rtx-arg1 rtx)))
     (if (symbol? ifield)
-       (current-ifield-lookup ifield)
+       (current-ifld-lookup ifield)
        ifield))
 )
 
        (obj:name operand)))
 )
 
-;; Given an operand rtx, construct the <operand> object.
+;; Given an operand rtx, return the <operand> object.
 ;; RTX must be canonical rtl.
-
-(define (rtx-operand-obj rtx)
-  (let ((op (current-op-lookup (rtx-arg1 rtx)))
-       (mode (rtx-mode rtx)))
+;; ISA-NAME-LIST is the list of ISAs to look the operand up in.
+;;
+;; NOTE: op:mode-name can be DFLT, which means use the mode of the type.
+;; It is up to the caller to deal with it.
+
+(define (rtx-operand-obj rtx isa-name-list)
+  (let ((op (current-op-lookup (rtx-arg1 rtx) isa-name-list))
+       (mode-name (rtx-mode rtx)))
     (assert op)
-    (assert (not (eq? mode 'DFLT)))
-    ;; NOTE: op:mode-name can be DFLT, which means use the mode of the type.
-    ;; But we can't propagate DFLT here, in canonical rtl DFLT is not allowed.
-    (if (mode:eq? (op:mode-name op) mode)
-       op
-       (op:new-mode op mode)))
+    (assert (not (eq? mode-name 'DFLT)))
+    ;; Ensure requested mode is supported by the hardware.
+    ;; rtx-canonicalize should have verified this already (I think).
+    (assert (hw-mode-ok? (op:type op) mode-name (op:index op)))
+    op)
 )
 
 (define (rtx-make-local mode-name local-name)
 (define (rtx-sequence-exprs rtx) (cddddr rtx))
 
 ; Same as rtx-sequence-locals except return in assq'able form.
-; ??? Sometimes I should it should have been (sequence ((name MODE)) ...)
+; ??? Sometimes I think it should have been (sequence ((name MODE)) ...)
 ; instead of (sequence ((MODE name)) ...) from the beginning, sigh.
 
 (define (rtx-sequence-assq-locals rtx)
         locals))
 )
 
+(define (rtx-closure-isas rtx) (list-ref rtx 3))
+(define (rtx-closure-env-stack rtx) (list-ref rtx 4))
+(define (rtx-closure-expr rtx) (list-ref rtx 5))
+
 ; Return a semi-pretty string describing RTX.
 ; This is used by hw to include the index in the element's name.
 
 ; HW-NAME/MODE-NAME/SELECTOR/INDEX-ARG.
 ;
 ; HW-NAME is the name of the hardware element.
+; MODE-NAME is the name of the mode.
 ; INDEX-ARG is an rtx or number of the index.
 ; In the case of scalar hardware elements, pass 0 for INDEX-ARG.
-; MODE-NAME is the name of the mode.
 ; In the case of a vector of registers, INDEX-ARG is the vector index.
-; In the case of a scalar register, the value is ignored, but pass 0 (??? #f?).
 ; SELECTOR is an rtx or number and is passed to HW-NAME to allow selection of a
 ; particular variant of the hardware.  It's kind of like an INDEX, but along
 ; an atypical axis.  An example is memory ASI's on Sparc.  Pass
 ; hw-selector-default if there is no selector.
 ; ESTATE is the current rtx evaluation state.
 ;
-; e.g. (hw estate WI h-gr #f (const INT 14))
-; selects register 14 of the h-gr set of registers.
-;
 ; *** The index is passed unevaluated because for parallel execution support
 ; *** a variable is created with a name based on the hardware element and
 ; *** index, and we want a reasonably simple and stable name.  We get this by
                 (cond ((number? index-arg)
                        (make <hw-index> 'anonymous 'constant UINT index-arg))
                       ((rtx? index-arg)
-                       ; For the simulator the following could be done which
-                       ; would save having to create a closure.
-                       ; ??? Old code, left in for now.
-                       ; (rtx-get estate DFLT
-                       ;          (rtx-eval (estate-context estate)
-                       ;                    (estate-econfig estate)
-                       ;                    index-arg rtx-evaluator))
                        ; Make sure constant indices are recorded as such.
                        (if (rtx-constant? index-arg)
                            (make <hw-index> 'anonymous 'constant UINT
index b4608e2..cbd0bcd 100644 (file)
 
 ; This has to be a syntax node to handle locals properly: they're not defined
 ; yet and thus pre-evaluating the expressions doesn't work.
-; ??? This should create a closure.
 
 (drsn (sequence &options &mode locals expr . exprs)
      #f
 )
 
 ; Internal rtx to create a closure.
-; Internal, so it does not appear in rtl.texi.
+; Internal, so it does not appear in rtl.texi (at least not yet).
+; ??? Maybe closures shouldn't be separate from sequences,
+; but I'm less convinced these days.
 
-(drsn (closure &options &mode expr env)
+(drsn (closure &options &mode isa-name-list env-stack expr)
      #f
-      (OPTIONS VOIDORNUMMODE RTX ENV) (NA NA MATCHEXPR NA)
+      (OPTIONS VOIDORNUMMODE SYMBOLLIST ENVSTACK RTX) (NA NA NA NA MATCHEXPR)
       MISC
       #f
 )
index bd03cd2..0fb26f4 100644 (file)
 
 (define (/frag-hash-stmt stmt locals size)
   (set! /frag-hash-value-tmp 0)
-  (rtx-traverse-with-locals #f #f stmt /frag-hash-compute! locals #f) ; FIXME: (/fastcall-make /frag-hash-compute!))
+  (rtx-traverse-with-locals #f #f stmt /frag-hash-compute! locals #f)
   (modulo /frag-hash-value-tmp size)
 )
 
 (define (/frag-stmt-cost stmt locals)
   (set! /frag-speed-cost-tmp 0)
   (set! /frag-size-cost-tmp 0)
-  (rtx-traverse-with-locals #f #f stmt /frag-cost-compute! locals #f) ; FIXME: (/fastcall-make /frag-cost-compute!))
+  (rtx-traverse-with-locals #f #f stmt /frag-cost-compute! locals #f)
   (cons /frag-speed-cost-tmp /frag-size-cost-tmp)
 )
 
                ; statements.
                stmt-numbers
 
-               ; Raw rtl source of fragment.
+               ; rtl source of fragment.
                semantics
 
-               ; Compiled source.
-               compiled-semantics
-
                ; Boolean indicating if this frag is for parallel exec support.
                parallel?
 
 )
 
 (define-getters <sfrag> sfrag
-  (users user-nums sfmt stmt-numbers semantics compiled-semantics
+  (users user-nums sfmt stmt-numbers semantics
         parallel? header? trailer?)
 )
 
                  (for-each
                   (lambda (users)
                     (let* ((first-owner (cdar users))
+                           (context (make-obj-context first-owner "While building sfrags"))
+                           (rtl (apply
+                                 rtx-make
+                                 (cons 'sequence
+                                       (cons 'VOID
+                                             (cons nil
+                                                   (map (lambda (stmt-num)
+                                                          (-stmt-expr
+                                                           (vector-ref stmt-table
+                                                                       stmt-num)))
+                                                        stmt-list))))))
                            (sfrag
                             (make <sfrag>
                               (symbol-append (obj:name first-owner)
                               (map car users)
                               (insn-sfmt first-owner)
                               stmt-list
-                              (apply
-                               rtx-make
-                               (cons 'sequence
-                                     (cons 'VOID
-                                           (cons nil
-                                                 (map (lambda (stmt-num)
-                                                        (-stmt-expr
-                                                         (vector-ref stmt-table
-                                                                     stmt-num)))
-                                                      stmt-list)))))
-                              #f ; compiled-semantics
+                              rtl
                               #f ; parallel?
                               (eq? kind 'header)
                               (eq? kind 'trailer)
                            (+ expr-num 1)
                            (cdr expr-middle-stmts))
                      ; Yep.
-                     (let ((owner (vector-ref owner-table expr-num)))
+                     (let* ((owner (vector-ref owner-table expr-num))
+                            (context (make-obj-context owner "While building sfrags"))
+                            (rtl (apply
+                                  rtx-make
+                                  (cons 'sequence
+                                        (cons 'VOID
+                                              (cons nil
+                                                    (map (lambda (stmt-num)
+                                                           (-stmt-expr
+                                                            (vector-ref stmt-table stmt-num)))
+                                                         (car expr-middle-stmts))))))))
                        (vector-set! (vector-ref expr-sfrags expr-num)
                                     1 next-middle-frag-num)
                        (loop (cons (make <sfrag>
                                      (list expr-num)
                                      (insn-sfmt owner)
                                      (car expr-middle-stmts)
-                                     (apply
-                                      rtx-make
-                                      (cons 'sequence
-                                            (cons 'VOID
-                                                  (cons nil
-                                                        (map (lambda (stmt-num)
-                                                               (-stmt-expr
-                                                                (vector-ref stmt-table stmt-num)))
-                                                             (car expr-middle-stmts))))))
-                                     #f ; compiled-semantics
+                                     rtl
                                      #f ; parallel?
                                      #f ; header?
                                      #f ; trailer?
                                      '(VIRTUAL) "")
                        nil ; users
                        nil ; user ordinals
-                       (insn-sfmt (current-insn-lookup 'x-before))
+                       (insn-sfmt (current-insn-lookup 'x-before #f))
                        #f ; stmt-numbers
                        (rtx-make 'nop)
-                       #f ; compiled-semantics
                        #f ; parallel?
                        #t ; header?
                        #f ; trailer?
                                      '(VIRTUAL) "")
                        nil ; users
                        nil ; user ordinals
-                       (insn-sfmt (current-insn-lookup 'x-before))
+                       (insn-sfmt (current-insn-lookup 'x-before #f))
                        #f ; stmt-numbers
                        (rtx-make 'nop)
-                       #f ; compiled-semantics
                        #f ; parallel?
                        #f ; header?
                        #t ; trailer?
index 306c431..7307467 100644 (file)
 ; Adds COND-CTI/UNCOND-CTI to SEM-ATTRS if the operand is a set of the pc.
 
 (define (/build-operand! op-expr tstate ref-type op-list sem-attrs)
-  (let* ((op (rtx-operand-obj op-expr))
+  (let* ((orig-op (rtx-operand-obj op-expr (obj-isa-list (tstate-owner tstate))))
         (mode (rtx-mode op-expr))
+        ;; We need a copy as we'll be modifying it.
+        (op (op:new-mode orig-op mode))
         ;; The first #f is a placeholder for the object.
         (try (list '-op- #f mode (rtx-arg1 op-expr) #f))
         (existing-op (/rtx-find-op try op-list)))
                   "only `(index-of operand)' is currently supported"
                   expr))
 
-  (let ((op (rtx-operand-obj (rtx-index-of-value expr))))
+  (let ((op (rtx-operand-obj (rtx-index-of-value expr)
+                            (obj-isa-list (tstate-owner tstate)))))
     (let ((indx (op:index op)))
       (if (not (eq? (hw-index:type indx) 'ifield))
          (parse-error (tstate-context tstate)
 (define (csem-outputs csem) (vector-ref csem 2))
 (define (csem-attrs csem) (vector-ref csem 3))
 \f
-; Traverse each element in SEM-CODE, converting them to canonical form,
-; and computing the input and output operands.
+; Traverse SEM-CODE, computing the input and output operands.
 ; The result is an object of four elements (built with csem-make).
 ; The first is a list of the canonical form of each element in SEM-CODE:
 ; operand and ifield elements specified without `operand' or `ifield' have it
 ;
 ; CONTEXT is a <context> object or #f if there is none.
 ; INSN is the <insn> object.
+; SEM-CODE must be canonicalized rtl.
 ;
 ; ??? Specifying operand ordinals in the source would simplify this and speed
 ; it up.  On the other hand that makes the source form more complex.  Maybe the
index 69b30d9..0b178b1 100644 (file)
@@ -111,7 +111,6 @@ namespace @arch@ {
        (name (obj:name hw))
        (getter (hw-getter hw))
        (setter (hw-setter hw))
-       (isas (obj-attr-value hw 'ISA))
        (type (gen-type hw)))
     (let ((get-code (if getter
                        (let ((mode (hw-mode hw))
@@ -119,10 +118,12 @@ namespace @arch@ {
                              (expr (cadr getter)))
                          (string-append
                           "return "
-                          (rtl-c++ mode expr
+                          (rtl-c++ mode
+                                   #f ;; h/w is not ISA-specific
                                    (if scalar?
                                        nil
                                        (list (list (car args) 'UINT "regno")))
+                                   expr
                                    #:rtl-cover-fns? #t)
                           ";"))
                        (string-append
@@ -135,11 +136,12 @@ namespace @arch@ {
                              (expr (cadr setter)))
                          (rtl-c++
                           VOID ; not `mode', sets have mode VOID
-                          expr
+                          #f ;; h/w is not ISA-specific
                           (if scalar?
                               (list (list (car args) (hw-mode hw) "newval"))
                               (list (list (car args) 'UINT "regno")
                                     (list (cadr args) (hw-mode hw) "newval")))
+                          expr
                           #:rtl-cover-fns? #t))
                        (string-append
                         "this->hardware."
@@ -704,26 +706,22 @@ using namespace cgen;
 ; Return C code to perform the semantics of INSN.
 
 (define (gen-semantic-code insn)
-  ; Indicate generating code for INSN.
-  ; Use the canonical form if available.
-  ; The case when they're not available is for virtual insns. (??? Still true?)
   (cond ((insn-compiled-semantics insn)
         => (lambda (sem)
-             (rtl-c++-parsed VOID sem nil
+             (rtl-c++-parsed VOID sem
                              #:for-insn? #t
                              #:rtl-cover-fns? #t
                              #:owner insn)))
        ((insn-canonical-semantics insn)
         => (lambda (sem)
-             (rtl-c++-parsed VOID sem nil
+             (rtl-c++-parsed VOID sem
                              #:for-insn? #t
                              #:rtl-cover-fns? #t
                              #:owner insn)))
        (else
-        (rtl-c++ VOID (insn-semantics insn) nil
-                 #:for-insn? #t
-                 #:rtl-cover-fns? #t
-                 #:owner insn)))
+        (context-error (make-obj-context insn #f)
+                       "While generating semantic code"
+                       "semantics of insn are not canonicalized")))
 )
 
 ; Return definition of C function to perform INSN.
@@ -894,7 +892,8 @@ using namespace @prefix@; // FIXME: namespace organization still wip\n"))
              (isa-setup-semantics (current-isa)))
         (string-append
          "      "
-         (rtl-c++ VOID (isa-setup-semantics (current-isa)) nil
+         (rtl-c++ VOID (obj-isa-list insn) nil
+                  (isa-setup-semantics (current-isa))
                   #:for-insn? #t
                   #:rtl-cover-fns? #t
                   #:owner insn))
@@ -1115,27 +1114,20 @@ struct @prefix@_pbb_label {
 ; Each element is (symbol <mode> "c-var-name").
 
 (define (/gen-sfrag-code frag locals)
-  ; Indicate generating code for FRAG.
-  ; Use the compiled form if available.
-  ; The case when they're not available is for virtual insns.
-  (let ((sem (sfrag-compiled-semantics frag))
+  (let ((sem (sfrag-semantics frag))
        ; If the frag has one owner, use it.  Otherwise indicate the owner is
        ; unknown.  In cases where the owner is needed by the semantics, the
        ; frag should have only one owner.  In practice this means that frags
        ; with the ref,current-insn rtx cannot be used by multiple insns.
        (owner (if (= (length (sfrag-users frag)) 1)
                   (car (sfrag-users frag))
-                  #f))
-       )
-    (if sem
-       (rtl-c++-parsed VOID sem locals
-                       #:for-insn? #t
-                       #:rtl-cover-fns? #t
-                       #:owner owner)
-       (rtl-c++ VOID (sfrag-semantics frag) locals
-                #:for-insn? #t
-                #:rtl-cover-fns? #t
-                #:owner owner)))
+                  #f)))
+    ;; NOTE: (sfrag-users frag) is nil for the x-header and x-trailer frags.
+    ;; They are just nops.
+    (rtl-c++ VOID (and owner (obj-isa-list owner)) locals sem
+            #:for-insn? #t
+            #:rtl-cover-fns? #t
+            #:owner owner))
 )
 
 ; Generate a switch case to perform FRAG.
@@ -1189,7 +1181,8 @@ struct @prefix@_pbb_label {
              (isa-setup-semantics (current-isa)))
         (string-append
          "      "
-         (rtl-c++ VOID (isa-setup-semantics (current-isa)) nil
+         (rtl-c++ VOID (list (obj:name (current-isa))) nil
+                  (isa-setup-semantics (current-isa))
                   #:rtl-cover-fns? #t
                   #:owner #f))
         "")
index d58adbc..999f47c 100644 (file)
@@ -609,7 +609,7 @@ static void
     (let ((decode-code (gen-decoder insn-list initial-bitnums
                                    decode-bitsize
                                    "    " lsb0?
-                                   (current-insn-lookup 'x-invalid)
+                                   (current-insn-lookup 'x-invalid #f)
                                    #t)))
 
       (string-write
index 113a958..72ecae9 100644 (file)
 ; Generate C code for SEL.
 
 (define (/gen-hw-selector sel)
-  (rtl-c++ 'INT sel nil)
+  (rtl-c++ INT #f nil sel)
 )
 \f
 ; Instruction operand support code.
  <pc> 'cxmake-skip
  (lambda (self estate yes?)
    (send (op:type self) 'cxmake-skip estate
-        (rtl-c++ INT yes? nil #:rtl-cover-fns? #t)))
+        (rtl-c++ INT (obj-isa-list self) nil yes? #:rtl-cover-fns? #t)))
 )
 
 ; Default gen-read method.
                         (getter
                          (let ((args (car getter))
                                (expr (cadr getter)))
-                           (rtl-c-expr mode expr
+                           (rtl-c-expr mode
+                                       (obj-isa-list self)
                                        (if (= (length args) 0) nil
                                            (list (list (car args) 'UINT index)))
+                                       expr
                                        #:rtl-cover-fns? #t
                                        #:output-language (estate-output-language estate))))
                         (else
    (if (op:setter op)
        (let ((args (car (op:setter op)))
             (expr (cadr (op:setter op))))
-        (rtl-c 'VOID expr
+        (rtl-c 'VOID
+               (obj-isa-list op)
                (if (= (length args) 0)
                    (list (list 'newval mode "opval"))
                    (list (list (car args) 'UINT index)
                          (list 'newval mode "opval")))
+               expr
                #:rtl-cover-fns? #t
                #:output-language (estate-output-language estate)))
        ;else
     pbb_br_status = BRANCH_UNTAKEN;
     UINT cond_code = abuf->cond;
     BI exec_p = "
-    (rtl-c++ DFLT (cadr (isa-condition isa)) '((cond-code UINT "cond_code"))
+    (rtl-c++ DFLT
+            (list (obj:name isa))
+            '((cond-code UINT "cond_code"))
+            (cadr (isa-condition isa))
             #:rtl-cover-fns? #t)
     ";
     if (! exec_p)
        ))
 
   ; Do our own error checking.
-  (assert (current-insn-lookup 'x-invalid))
+  (assert (current-insn-lookup 'x-invalid #f))
 
   *UNSPECIFIED*
 )
index e083c63..3b85498 100644 (file)
@@ -534,7 +534,8 @@ SEM_FN_NAME (@prefix@,init_idesc_table) (SIM_CPU *current_cpu)
            (isa-setup-semantics (current-isa)))
        (string-append
        "  "
-       (rtl-c VOID (isa-setup-semantics (current-isa)) nil
+       (rtl-c VOID (obj-isa-list insn) nil
+              (isa-setup-semantics (current-isa))
               #:for-insn? #t
               #:rtl-cover-fns? #t
               #:owner insn)
@@ -543,24 +544,23 @@ SEM_FN_NAME (@prefix@,init_idesc_table) (SIM_CPU *current_cpu)
 
    ; Indicate generating code for INSN.
    ; Use the compiled form if available.
-   ; The case when they're not available is for virtual insns. (??? Still true?)
+   ; The case when they're not available is for virtual insns. xxx Still true?
    (cond ((insn-compiled-semantics insn)
          => (lambda (sem)
-              (rtl-c-parsed VOID sem nil
+              (rtl-c-parsed VOID sem
                             #:for-insn? #t
                             #:rtl-cover-fns? #t
                             #:owner insn)))
         ((insn-canonical-semantics insn)
          => (lambda (sem)
-              (rtl-c-parsed VOID sem nil
+              (rtl-c-parsed VOID sem
                             #:for-insn? #t
                             #:rtl-cover-fns? #t
                             #:owner insn)))
         (else
-         (rtl-c VOID (insn-semantics insn) nil
-                #:for-insn? #t
-                #:rtl-cover-fns? #t
-                #:owner insn))))
+         (context-error (make-obj-context insn #f)
+                        "While generating semantic code"
+                        "semantics of insn are not canonicalized"))))
 )
 
 ; Return definition of C function to perform INSN.
@@ -1272,7 +1272,7 @@ xfull-extract-* | xfast-extract-*)
 cat <<EOF
 {
 "
-   (rtl-c VOID insn-extract nil #:rtl-cover-fns? #t)
+   (rtl-c VOID #f nil insn-extract #:rtl-cover-fns? #t)
 "}
 EOF
 
@@ -1283,7 +1283,7 @@ xfull-exec-* | xfast-exec-*)
 cat <<EOF
 {
 "
-   (rtl-c VOID insn-execute nil #:rtl-cover-fns? #t)
+   (rtl-c VOID #f nil insn-execute #:rtl-cover-fns? #t)
 "}
 EOF
 
index 3d1a1e3..091b2f7 100644 (file)
@@ -489,7 +489,7 @@ void
     (let ((decode-code (gen-decoder insn-list initial-bitnums
                                    decode-bitsize
                                    "    " lsb0?
-                                   (current-insn-lookup 'x-invalid)
+                                   (current-insn-lookup 'x-invalid #f)
                                    #f)))
 
       (string-write
index 00baa52..8176070 100644 (file)
@@ -20,7 +20,8 @@
 (define (sim-test-analyze!)
   (opcodes-analyze!)
   (map (lambda
-          (insn) (elm-xset! insn 'tmp (syntax-break-out (insn-syntax insn))))
+          (insn) (elm-xset! insn 'tmp (syntax-break-out (insn-syntax insn)
+                                                        (obj-isa-list insn))))
        (current-insn-list))
   *UNSPECIFIED*
 )
index f5c8320..b0512c6 100644 (file)
               (expr (cadr getter)))
           (gen-get-macro (gen-sym self)
                          (if (hw-scalar? self) "" "index")
-                         (rtl-c mode expr
+                         (rtl-c mode
+                                #f ;; h/w is not ISA-specific
                                 (if (hw-scalar? self)
                                     nil
                                     (list (list (car args) 'UINT "index")))
+                                expr
                                 #:rtl-cover-fns? #t)))
         (send self 'gen-sym-get-macro
               (obj:name self) (obj:comment self)))))
                               ""
                               "index")
                           "x"
-                          (rtl-c VOID ; not `mode', sets have mode VOID
-                                 expr
+                          (rtl-c VOID ;; not `mode', sets have mode VOID
+                                 #f ;; h/w is not ISA-specific
                                  (if (hw-scalar? self)
                                      (list (list (car args) (hw-mode self) "(x)"))
                                      (list (list (car args) 'UINT "(index)")
                                            (list (cadr args) (hw-mode self) "(x)")))
+                                 expr
                                  #:rtl-cover-fns? #t #:macro? #t)))
         (send self 'gen-sym-set-macro
               (obj:name self) (obj:comment self)))))
 ; Generate C code for SEL.
 
 (define (/gen-hw-selector sel)
-  (rtl-c 'INT sel nil)
+  (rtl-c INT #f nil sel)
 )
 \f
 ; Instruction operand support code.
  <pc> 'cxmake-skip
  (lambda (self estate yes?)
    (send (op:type self) 'cxmake-skip estate
-        (rtl-c INT yes? nil #:rtl-cover-fns? #t)))
+        (rtl-c INT (obj-isa-list self) nil yes? #:rtl-cover-fns? #t)))
 )
 
 ; For parallel write post-processing, we don't want to defer setting the pc.
 ; For operands, the word `read' is only used in this context.
 
 (define (op:read op sfmt)
-  (let ((estate (estate-make-for-rtl-c nil nil)))
+  (let ((estate (estate-make-for-rtl-c nil)))
     (send op 'gen-read estate sfmt /par-operand-macro))
 )
 
 ; For operands, the word `write' is only used in this context.
 
 (define (op:write op sfmt)
-  (let ((estate (estate-make-for-rtl-c nil nil)))
+  (let ((estate (estate-make-for-rtl-c nil)))
     (send op 'gen-write estate sfmt /par-operand-macro))
 )
 
           ((op:getter self)
            (let ((args (car (op:getter self)))
                  (expr (cadr (op:getter self))))
-             (rtl-c-expr mode expr
+             (rtl-c-expr mode
+                         (obj-isa-list self)
                          (if (= (length args) 0)
                              nil
                              (list (list (car args) 'UINT index)))
+                         expr
                          #:rtl-cover-fns? #t)))
           (else
            (send (op:type self) 'cxmake-get estate mode index selector)))))
    (if (op:setter op)
        (let ((args (car (op:setter op)))
             (expr (cadr (op:setter op))))
-        (rtl-c 'VOID expr
+        (rtl-c VOID
+               (obj-isa-list op)
                (if (= (length args) 0)
                    (list (list 'newval mode "opval"))
                    (list (list (car args) 'UINT index)
                          (list 'newval mode "opval")))
+               expr
                #:rtl-cover-fns? #t))
        ;else
        (send (op:type op) 'gen-set-quiet estate mode index selector
 ; smart enough to know there is no need.
 
 (define (op:record-profile op sfmt out?)
-  (let ((estate (estate-make-for-rtl-c nil nil)))
+  (let ((estate (estate-make-for-rtl-c nil)))
     (send op 'gen-record-profile sfmt out? estate))
 )
 
@@ -2089,7 +2096,7 @@ struct scache {
        (set! /sim-insns-analyzed? #t)))
 
   ; Do our own error checking.
-  (assert (current-insn-lookup 'x-invalid))
+  (assert (current-insn-lookup 'x-invalid #f))
 
   *UNSPECIFIED*
 )
index daeef6e..e98ecca 100644 (file)
 ; Ideally most, if not all, of the guts of the generated sanitization is here.
 
 ; Utility to simplify expression in .cpu file.
-; Usage: (sanitize keyword entry-type entry-name1 [entry-name2 ...])
+; Usage: (sanitize isa-name-list keyword entry-type entry-name1 [entry-name2 ...])
 ; Enum attribute `(sanitize keyword)' is added to the entry.
-; It's written this way so Hobbit can handle it.
 
-(define (sanitize keyword entry-type . entry-names)
+(define (sanitize isa-name-list keyword entry-type . entry-names)
   (for-each (lambda (entry-name)
              (let ((entry #f))
                (case entry-type
                  ((cpu) (set! entry (current-cpu-lookup entry-name)))
                  ((mach) (set! entry (current-mach-lookup entry-name)))
                  ((model) (set! entry (current-model-lookup entry-name)))
-                 ((ifield) (set! entry (current-ifld-lookup entry-name)))
+                 ((ifield) (set! entry (current-ifld-lookup entry-name isa-name-list)))
                  ((hardware) (set! entry (current-hw-lookup entry-name)))
-                 ((operand) (set! entry (current-op-lookup entry-name)))
-                 ((insn) (set! entry (current-insn-lookup entry-name)))
-                 ((macro-insn) (set! entry (current-minsn-lookup entry-name)))
+                 ((operand) (set! entry (current-op-lookup entry-name isa-name-list)))
+                 ((insn) (set! entry (current-insn-lookup entry-name isa-name-list)))
+                 ((macro-insn) (set! entry (current-minsn-lookup entry-name isa-name-list)))
                  (else (parse-error (make-prefix-context "sanitize")
                                     "unknown entry type" entry-type)))
 
index 0ae3006..ec83686 100644 (file)
        ; cadr: fetches expression to be evaluated
        ; caar: fetches symbol in arglist
        ; cadar: fetches `pc' symbol in arglist
-       (rtl-c DFLT (cadr decode)
+       (rtl-c DFLT
+              (obj-isa-list f)
               (list (list (caar decode) 'UINT extraction)
                     (list (cadar decode) 'IAI "pc"))
+              (cadr decode)
               #:rtl-cover-fns? #f #:ifield-var? #t)))
 )
 
         ; cadr: fetches expression to be evaluated
         ; caar: fetches symbol in arglist
         ; cadar: fetches `pc' symbol in arglist
-        (rtl-c DFLT (cadr decode)
+        (rtl-c DFLT
+               (obj-isa-list f)
                (list (list (caar decode) 'UINT extraction)
                      (list (cadar decode) 'IAI "pc"))
+               (cadr decode)
                #:rtl-cover-fns? #f #:ifield-var? #t)))
 )
 
         (varname (gen-sym f))
         (decode (string-list
                  ;; First, the block that extract the multi-ifield into the ifld variable.
-                 (rtl-c VOID (multi-ifld-extract f) nil
+                 (rtl-c VOID (obj-isa-list f) nil
+                        (multi-ifld-extract f)
                         #:rtl-cover-fns? #f #:ifield-var? #t)
                  ;; Next, the decode routine that modifies it.
                  (if decode-proc
                      (string-append
                       "  " varname " = "
-                      (rtl-c DFLT (cadr decode-proc)
+                      (rtl-c DFLT
+                             (obj-isa-list f)
                              (list (list (caar decode-proc) 'UINT varname)
                                    (list (cadar decode-proc) 'IAI "pc"))
+                             (cadr decode-proc)
                              #:rtl-cover-fns? #f #:ifield-var? #t)
                       ";\n")
                      "")
index 5ba87fe..22e8a23 100644 (file)
 (define (intersection a b) 
   (foldl (lambda (l e) (if (memq e a) (cons e l) l)) '() b))
 
+; Return #t if the intersection of A and B is non-null.
+
+(define (non-null-intersection? a b)
+  (let loop ((todo a))
+    (cond ((null? todo)
+          #f)
+         ((memq (car todo) b)
+          #t)
+         (else
+          (loop (cdr todo)))))
+)
+
 ; Return union of two lists.
 
 (define (union a b)