; Standard RTL functions. ; Copyright (C) 2000, 2009, 2010 Red Hat, Inc. ; This file is part of CGEN. ; See file COPYING.CGEN for details. ; THIS FILE CONTAINS ONE BIG FUNCTION: def-rtx-funcs. ; ; It is ok for this file to use procs "internal" to rtl.scm. ; ; Each rtx functions has two leading operands: &options, &mode; ; though `&mode' may be spelled differently. ; The "&" prefix is to indicate that the parsing of these operands is handled ; differently. They are optional and are written with leading colons ; (e.g. :SI). The leading ":" is to help the parser - all leading optional ; operands begin with ":". The order of the arguments is &options then &mode ; though there is no imposed order in written RTL. (define (def-rtx-funcs) ; Do not change the indentation here. (let ( ; These are defined in rtl.scm. (drn define-rtx-node) (drsn define-rtx-syntax-node) (dron define-rtx-operand-node) (drmn define-rtx-macro-node) ) ; The reason for the odd indenting above is so that emacs begins indenting the ; following code at column 1. ; Error reporting. ; MODE is present for use in situations like non-VOID mode cond's. ; The code will expect the mode to be compatible even though `error' ; "doesn't return". A small concession for simpler code. (drn (error &options &mode message) #f (OPTIONS VOIDORNUMMODE STRING) (NA NA NA) MISC (estate-error *estate* "error in rtl" message) ) ; Enums ; Default mode is INT. (drn (enum &options &mode enum-name) #f (OPTIONS ANYINTMODE SYMBOL) (NA NA NA) ;; ??? s/SYMBOL/ENUM-NAME/ ? ARG ;; When computing a value, return the enum's value. ;; Canonicalization should have already caught bad values. (car (enum-lookup-val enum-name)) ) ; Instruction fields ; These are used in the encode/decode specs of other ifields as well as in ; instruction semantics. ; Ifields are normally specified by name, but they are subsequently wrapped ; in this. (dron (ifield &options &mode ifld-name) #f (OPTIONS ANYNUMMODE SYMBOL) (NA NA NA) ;; ??? s/SYMBOL/IFIELD-NAME/ ? ARG (let ((f (current-ifld-lookup ifld-name))) (make (obj-location f) ifld-name (string-append ifld-name " used as operand") (atlist-cons (bool-attr-make 'SEM-ONLY #t) (obj-atlist f)) (obj:name (ifld-hw-type f)) (obj:name (ifld-mode f)) (make 'anonymous 'ifield (ifld-mode f) f) nil #f #f)) ) ; Specify an operand. ; Operands are normally specified by name, but they are subsequently wrapped ; in this. (dron (operand &options &mode op-name) #f (OPTIONS ANYNUMMODE SYMBOL) (NA NA NA) ;; ??? s/SYMBOL/OPERAND-NAME/ ? ARG (current-op-lookup op-name) ) ; Operand naming/numbering. ; Operands are given names so that the operands as used in the semantics can ; be matched with arguments of function units. With good name choices of ; operands and function unit arguments, this is rarely necessary, but ; sometimes it is. ; ; ??? This obfuscates the semantic code a fair bit. Another way to do this ; would be to add new elements to to specify operands outside of ; the semantic code. E.g. ; (define-insn ... ; (inputs (in-gr1 src1) (in-gr2 src2)) ; (outputs (out-pc pc) (out-gr dr) (reg-14 (reg WI h-gr 14))) ; ...) ; The intent here is to continue to allow the semantic code to use names ; of operands, and not overly complicate the input/output description. ; ; In instructions, operand numbers are recorded as well, to implement ; profiling and result writeback of parallel insns. ; Rename operand VALUE to NEW-NAME. ; VALUE is an expression whose result is an object of type . ; It can be the name of an existing operand. ; ??? Might also support numbering by allowing NEW-NAME to be a number. (drsn (name &options &mode new-name value) #f (OPTIONS ANYNUMMODE SYMBOL RTX) (NA NA NA ANY) ARG ;; FIXME: s/DFLT/&mode/ ? (let ((result (object-copy (rtx-get 'DFLT value)))) (op:set-sem-name! result new-name) result) ) ; Operands are generally compiled to an internal form first. ; There is a fair bit of state associated with them, and it's easier to ; work with an object than source [which might get fairly complicated if ; it expresses all the state]. ; Compiled operands are wrapped in this so that they still look like rtx. (dron (xop &options &mode object) #f (OPTIONS ANYNUMMODE OBJECT) (NA NA NA) ;; ??? s/OBJECT/OPERAND/ ? ARG object ) ;(dron (opspec: &options &mode op-name op-num hw-ref attrs) ; (OPTIONS ANYNUMMODE SYMBOL NUMBER RTX ATTRS) (NA NA NA NA ANY NA) ; ARG ; (let ((opval (rtx-eval-with-estate hw-ref (mode:lookup &mode) *estate*))) ; (assert (operand? opval)) ; ; Set the specified mode, ensuring it's ok. ; ; This also makes a copy as we don't want to modify predefined ; ; operands. ; (let ((operand (op:new-mode opval mode))) ; (op:set-sem-name! operand op-name) ; (op:set-num! operand op-num) ; (op:set-cond?! operand (attr-value attrs 'COND-REF #f)) ; operand)) ;) ; Specify a reference to a local variable. ; Local variables are normally specified by name, but they are subsequently ; wrapped in this. (dron (local &options &mode local-name) #f (OPTIONS ANYNUMMODE SYMBOL) (NA NA NA) ;; ??? s/SYMBOL/LOCAL-NAME/ ? ARG (rtx-temp-lookup (tstate-env *tstate*) local-name) ) ; FIXME: This doesn't work. See s-operand. ;(define (s-dup estate op-name) ; (if (not (insn? (estate-owner estate))) ; (error "dup: not processing an insn")) ; (vector-ref (insn:operands (current-current-context)) ; (op:lookup-num (insn:operands (estate-owner estate)) op-name)) ;) ; ; ??? Since operands are given names and not numbers this isn't currently used. ; ;(drsn (dup &options &mode op-name) ; #f ; (OPTIONS ANYNUMMODE SYMBOL) (NA NA NA) ; ;(s-dup *estate* op-name) ; (begin ; (if (not (insn? (estate-owner *estate*))) ; (error "dup: not processing an insn")) ; (vector-ref (insn:operands (estate-owner *estate*)) ; (op:lookup-num (insn:operands (estate-owner *estate*)) op-name))) ; #f ;) ; Returns non-zero if operand NAME was referenced (read if input operand ; and written if output operand). ; ??? What about input/output operands. (drsn (ref &options &mode name) BI (OPTIONS BIMODE SYMBOL) (NA NA NA) ;; ??? s/SYMBOL/OPERAND-NAME/ ? ARG #f ) ; Return the index of an operand. ; For registers this is the register number. ; ??? Mode handling incomplete, this doesn't handle mem, which it could. ; Until then we fix the mode of the result to INT. (dron (index-of &options &mode op-rtx) INT (OPTIONS INTMODE RTX) (NA NA ANY) ARG ;; FIXME: s/DFLT/&mode/ ? (let* ((operand (rtx-eval-with-estate op-rtx DFLT *estate*)) (f (hw-index:value (op:index operand))) (f-name (obj:name f))) (make (if (source-ident? f) (obj-location f) #f) f-name f-name (atlist-cons (bool-attr-make 'SEM-ONLY #t) (obj-atlist f)) (obj:name (ifld-hw-type f)) (obj:name (ifld-mode f)) (make 'anonymous 'ifield (ifld-mode f) ; (send (op:type op) 'get-index-mode) f) nil #f #f)) ) ; Same as index-of, but improves readability for registers. (drmn (regno reg) (list 'index-of reg) ) ; Hardware elements. ; Describe a random hardware object. ; If INDX is missing, assume the element is a scalar. We pass 0 so s-hw ; doesn't have to unpack the list that would be passed if it were defined as ; (hw mode hw-name . indx). This is an internal implementation detail ; and thus harmless to the description language. ; These are implemented as syntax nodes as we must pass INDX to `s-hw' ; unevaluated. ; ??? Not currently supported. Not sure whether it should be. ;(drsn (hw &options &mode hw-elm . indx-sel) ; (OPTIONS ANYNUMMODE SYMBOL . RTX) (NA NA NA . INT) ; ARG ; (let ((indx (if (pair? indx-sel) (car indx-sel) 0)) ; (selector (if (and (pair? indx-sel) (pair? (cdr indx-sel))) ; (cadr indx-sel) ; hw-selector-default)))) ; (s-hw *estate* mode hw-elm indx selector) ;) ; Register accesses. ; INDX-SEL is an optional index and possible selector. (dron (reg &options &mode hw-elm . indx-sel) #f (OPTIONS ANYNUMMODE SYMBOL . RTX) (NA NA NA . INT) ;; ??? s/SYMBOL/HW-NAME/ ? ARG (let ((indx (if (pair? indx-sel) (car indx-sel) 0)) (selector (if (and (pair? indx-sel) (pair? (cdr indx-sel))) (cadr indx-sel) hw-selector-default))) (s-hw *estate* mode hw-elm indx selector)) ) ; A raw-reg bypasses the getter/setter stuff. It's usually used in ; getter/setter definitions. (dron (raw-reg &options &mode hw-elm . indx-sel) #f (OPTIONS ANYNUMMODE SYMBOL . RTX) (NA NA NA . INT) ;; ??? s/SYMBOL/HW-NAME/ ? ARG (let ((indx (if (pair? indx-sel) (car indx-sel) 0)) (selector (if (and (pair? indx-sel) (pair? (cdr indx-sel))) (cadr indx-sel) hw-selector-default))) (let ((result (s-hw *estate* mode hw-elm indx selector))) (obj-cons-attr! result (bool-attr-make 'RAW #t)) result)) ) ; Memory accesses. (dron (mem &options &mode addr . sel) #f (OPTIONS EXPLNUMMODE RTX . RTX) (NA NA AI . INT) ARG (s-hw *estate* mode 'h-memory addr (if (pair? sel) (car sel) hw-selector-default)) ) ; Instruction execution support. ; There are no jumps, per se. A jump is a set of `pc'. ; The program counter. ; ??? Hmmm... needed? The pc is usually specified as `pc' which is shorthand ; for (operand pc). ;(dron (pc) () () ARG s-pc) ; Fetch bytes from the instruction stream of size MODE. ; FIXME: Later need to augment this by passing an indicator to the mem-fetch ; routines that we're doing an ifetch. ; ??? wip! (drmn (ifetch mode pc) (list 'mem mode pc) ; hw-selector-ispace ) ; NUM is the instruction number. Generally it is zero but if more than one ; insn is decoded at a time, it is non-zero. This is used, for example, to ; index into the scache [as an offset from the first insn]. ; ??? wip! (drmn (decode mode pc insn num) (list 'c-call mode 'EXTRACT pc insn num) ) ; NUM is the same number passed to `decode'. ; ??? wip! (drmn (execute mode num) (list 'c-call mode 'EXECUTE num) ) ; Control Transfer Instructions ; Sets of pc are handled like other sets so there are no branch rtx's. ; Indicate there are N delay slots in the processing of RTX. ; N is a `const' node. ; The mode of the result is the mode of RTX. ; ??? wip! (drn (delay &options &mode n rtx) #f (OPTIONS VOIDORNUMMODE RTX RTX) (NA NA INT MATCHEXPR) MISC #f ; (s-sequence *estate* VOID '() rtx) ; wip! ) ; Annul the following insn if YES? is non-zero. ; PC is the address of the annuling insn. ; The target is required to define SEM_ANNUL_INSN. ; ??? wip! (drmn (annul yes?) ; The pc reference here is hidden in c-code to not generate a spurious ; pc input operand. (list 'c-call 'VOID "SEM_ANNUL_INSN" (list 'c-code 'IAI "pc") yes?) ) ; Skip the following insn if YES? is non-zero. ; The target is required to define SEM_SKIP_INSN. ; ??? This is similar to annul. Deletion of one of them defered. ; ??? wip! (drn (skip &options &mode yes?) VOID (OPTIONS VOIDMODE RTX) (NA NA INT) MISC #f ) ; Attribute support. ; Return a boolean indicating if attribute named ATTR is VALUE in OWNER. ; If VALUE is a list, return "true" if ATTR is any of the listed values. ; ??? Don't yet support !VALUE. ; OWNER is the result of either (current-insn) or (current-mach) ; [note that canonicalization will turn them into ; (current-{insn,mach} () DFLT)]. ; The result is always of mode BI. ; FIXME: wip ; ; This is a syntax node so the args are not pre-evaluated. ; We just want the symbols. ; FIXME: Hmmm... it currently isn't a syntax node. (drn (eq-attr &options &mode owner attr value) BI (OPTIONS BIMODE RTX SYMBOL SYMORNUM) (NA NA ANY NA NA) MISC (let ((atval (if owner (obj-attr-value owner attr) (attr-lookup-default attr #f)))) (if (list? value) (->bool (memq atval value)) (eq? atval value))) ) ; Get the value of attribute ATTR-NAME, expressable as an integer. ; OBJ is the result of either (current-insn) or (current-mach). ; Note that canonicalization will turn them into ; (current-{insn,mach} () {INSN,MACH}MODE). ; FIXME:wip ; This uses INTMODE because we can't otherwise determine the ; mode of the result (if elided). (drn (int-attr &options &mode obj attr-name) #f (OPTIONS INTMODE RTX SYMBOL) (NA NA ANY NA) MISC #f ) ;; Deprecated alias for int-attr. (drmn (attr arg1 . rest) (cons 'int-attr (cons arg1 rest)) ) ; Same as `quote', for use in attributes cus "quote" sounds too jargonish. ; [Ok, not a strong argument for using "symbol", but so what?] (drsn (symbol &options &mode name) SYM (OPTIONS SYMMODE SYMBOL) (NA NA NA) ARG name ) ; Return the current instruction. (drn (current-insn &options &mode) INSN (OPTIONS INSNMODE) (NA NA) MISC (let ((obj (estate-owner *estate*))) (if (not (insn? obj)) (error "current context not an insn")) obj) ) ; Return the currently selected machine. ; This can either be a compile-time or run-time value. (drn (current-mach &options &mode) MACH (OPTIONS MACHMODE) (NA NA) MISC -rtx-current-mach ) ; Constants. ; FIXME: Need to consider 64 bit hosts. (drn (const &options &mode c) #f (OPTIONS ANYNUMMODE NUMBER) (NA NA NA) ARG ; When computing a value, just return the constant unchanged. c ) ; Large mode support. ; Combine smaller modes into a larger one. ; Arguments are specified most significant to least significant. ; ??? Not all of the combinations are supported in the simulator. ; They'll get added as necessary. (drn (join &options &out-mode in-mode arg1 . arg-rest) #f (OPTIONS ANYNUMMODE ANYNUMMODE RTX . RTX) (NA NA NA ANY . ANY) MISC ; FIXME: Ensure correct number of args for in/out modes. ; FIXME: Ensure compatible modes. #f ) ; GCC's subreg. ; Called subword 'cus it's not exactly subreg. ; Word numbering is word-order dependent. ; Word number 0 is the most significant word if big-endian-words. ; Word number 0 is the least significant word if little-endian-words. ; ??? GCC plans to switch to SUBREG_BYTE. Keep an eye out for the switch ; (which is extensive so probably won't happen anytime soon). ; MODE is the mode of the result, not operand0. ; ; The mode spec of operand0 use to be MATCHEXPR, but subword is not a normal rtx. ; The mode of operand0 is not necessarily the same as the mode of the result, ; and code which analyzes it would otherwise use the result mode (specified by ; `&mode') for the mode of operand0. (drn (subword &options &mode value word-num) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA ANY INT) ARG #f ) ; ??? The split and concat stuff is just an experiment and should not be used. ; What's there now is just "thoughts put down on paper." (drmn (split split-mode in-mode di) ; FIXME: Ensure compatible modes ;(list 'c-raw-call 'BLK (string-append "SPLIT" in-mode split-mode) di) '(const 0) ) (drmn (concat modes arg1 . arg-rest) ; FIXME: Here might be the place to ensure ; (= (length modes) (length (cons arg1 arg-rest))). ;(cons 'c-raw-call (cons modes (cons "CONCAT" (cons arg1 arg-rest)))) '(const 0) ) ; Support for explicit C code. ; ??? GCC RTL calls this "unspec" which is arguably a more application ; independent name. (drn (c-code &options &mode text) #f (OPTIONS ANYCEXPRMODE STRING) (NA NA NA) UNSPEC #f ) ; Invoke C functions passing them arguments from the semantic code. ; The arguments are passed as is, no conversion is done here. ; Usage is: ; (c-call mode name arg1 arg2 ...) ; which is converted into a C function call: ; name (current_cpu, arg1, arg2, ...) ; MODE is the mode of the result. ; If it is VOID this call is a statement and ';' is appended. ; Otherwise it is part of an expression. (drn (c-call &options &mode name . args) #f (OPTIONS ANYCEXPRMODE STRING . RTX) (NA NA NA . ANY) UNSPEC #f ) ; Same as c-call but without implicit first arg of `current_cpu'. (drn (c-raw-call &options &mode name . args) #f (OPTIONS ANYCEXPRMODE STRING . RTX) (NA NA NA . ANY) UNSPEC #f ) ; Set/get/miscellaneous (drn (nop &options &mode) VOID (OPTIONS VOIDMODE) (NA NA) MISC #f ) ; Clobber - mark an object as modified without explaining why or how. (drn (clobber &options &mode object) VOID (OPTIONS VOIDORNUMMODE RTX) (NA NA MATCHEXPR) MISC #f ) ; The `set' rtx. ; MODE is the mode of DST. If DFLT, use DST's default mode. ; The mode of the result is always VOID. ; ; ??? It might be more consistent to rename set -> set-trace, but that's ; too wordy. The `set' rtx is the normal one and we want the normal one to ; be the verbose one (prints result tracing messages). `set-quiet' is the ; atypical one, it doesn't print tracing messages. It may also turn out that ; a different mechanism (rather than the name "set-quiet") is used some day. ; One way would be to record the "quietness" state with the traversal state and ; use something like (with-quiet (set foo bar)) akin to with-output-to-string ; in Guile. ; ; i.e. set -> gen-set-trace ; set-quiet -> gen-set-quiet ; ; ??? One might want a `!' suffix as in `set!', but methinks that's following ; Scheme too closely. (drn (set &options &mode dst src) VOID (OPTIONS ANYNUMMODE SETRTX RTX) (NA NA MATCHEXPR MATCH2) SET #f ) (drn (set-quiet &options &mode dst src) VOID (OPTIONS ANYNUMMODE SETRTX RTX) (NA NA MATCHEXPR MATCH2) SET #f ) ; Standard arithmetic operations. ; It's nice emitting macro calls to the actual C operation in that the RTX ; expression is preserved, albeit in C. On the one hand it's one extra thing ; the programmer has to know when looking at the code. But on the other it's ; trivial stuff, and having a layer between RTX and C allows the ; macros/functions to be modified to handle unexpected situations. ; ; We do emit C directly for cases other than cpu semantics ; (e.g. the assembler). ; ; The language is defined such that we assume ANSI C semantics while avoiding ; implementation defined areas, with as few exceptions as possible. ; ; Current exceptions: ; - signed shift right assumes the sign bit is replicated. ; ; Additional notes [perhaps repeating what's in ANSI C for emphasis]: ; - callers of division and modulus fns must test for 0 beforehand ; if necessary ; - division and modulus fns have unspecified behavior for negative args ; [yes I know the C standard says implementation defined, here its ; unspecified] ; - later add versions of div/mod that have an explicit behaviour for -ve args ; - signedness is part of the rtx operation name, and is not determined ; from the arguments [elsewhere is a description of the tradeoffs] ; - ??? (drn (neg &options &mode s1) #f (OPTIONS ANYNUMMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (abs &options &mode s1) #f (OPTIONS ANYNUMMODE RTX) (NA NA MATCHEXPR) UNARY #f ) ; For integer values this is a bitwise operation (each bit inverted). ; For floating point values this produces 1/x. ; ??? Might want different names. (drn (inv &options &mode s1) #f (OPTIONS ANYINTMODE RTX) (NA NA MATCHEXPR) UNARY #f ) ; This is a boolean operation. ; MODE is the mode of S1. The result always has mode BI. ; ??? Perhaps `mode' shouldn't be here. (drn (not &options &mode s1) BI (OPTIONS ANYINTMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (add &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (sub &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) ; "OF" for "overflow flag", "CF" for "carry flag", ; "s3" here must have type BI. ; For the *flag rtx's, MODE is the mode of S1,S2; the result always has ; mode BI. (drn (addc &options &mode s1 s2 s3) #f (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (addc-cflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (addc-oflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (subc &options &mode s1 s2 s3) #f (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (subc-cflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (subc-oflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) ;; ??? These are deprecated. Delete in time. (drn (add-cflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (add-oflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (sub-cflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) (drn (sub-oflag &options &mode s1 s2 s3) BI (OPTIONS ANYINTMODE RTX RTX RTX) (NA NA MATCHEXPR MATCH2 BI) TRINARY #f ) ; Usurp these names so that we have consistent rtl should a program generator ; ever want to infer more about what the semantics are doing. ; For now these are just macros that expand to real rtl to perform the ; operation. ; Return bit indicating if VALUE is zero/non-zero. (drmn (zflag arg1 . rest) ; mode value) (if (null? rest) ; mode missing? (list 'eq 'DFLT arg1 0) (list 'eq arg1 (car rest) 0)) ) ; Return bit indicating if VALUE is negative/non-negative. (drmn (nflag arg1 . rest) ; mode value) (if (null? rest) ; mode missing? (list 'lt 'DFLT arg1 0) (list 'lt arg1 (car rest) 0)) ) ; Multiply/divide. (drn (mul &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) ; ??? In non-sim case, ensure s1,s2 is in right C type for right result. ; ??? Need two variants, one that avoids implementation defined situations ; [both host and target], and one that specifies implementation defined ; situations [target]. (drn (div &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (udiv &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (mod &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (umod &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) ; wip: mixed mode mul/div ; various floating point routines (drn (sqrt &options &mode s1) #f (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (cos &options &mode s1) #f (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (sin &options &mode s1) #f (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (nan &options &mode s1) BI (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (qnan &options &mode s1) BI (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) (drn (snan &options &mode s1) BI (OPTIONS ANYFLOATMODE RTX) (NA NA MATCHEXPR) UNARY #f ) ; min/max (drn (min &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (max &options &mode s1 s2) #f (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (umin &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (umax &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) ; These are bitwise operations. (drn (and &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (or &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) (drn (xor &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR MATCH2) BINARY #f ) ; Shift operations. (drn (sll &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR INT) BINARY #f ) (drn (srl &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR INT) BINARY #f ) ; ??? In non-sim case, ensure s1 is in right C type for right result. (drn (sra &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR INT) BINARY #f ) ; Rotates don't really have a sign, so doesn't matter what we say. (drn (ror &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR INT) BINARY #f ) (drn (rol &options &mode s1 s2) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA MATCHEXPR INT) BINARY #f ) ; ??? Will also need rotate-with-carry [duh...]. ; These are boolean operations (e.g. C &&, ||). ; The result always has mode BI. ; ??? 'twould be more Schemey to take a variable number of args. ; ??? 'twould also simplify several .cpu description entries. ; On the other hand, handling an arbitrary number of args isn't supported by ; ISA's, which the main goal of what we're trying to represent. (drn (andif &options &mode s1 s2) BI (OPTIONS BIMODE RTX RTX) (NA NA ANYINT ANYINT) BINARY ; IF? #f ) (drn (orif &options &mode s1 s2) BI (OPTIONS BIMODE RTX RTX) (NA NA ANYINT ANYINT) BINARY ; IF? #f ) ; `bitfield' is an experimental operation. ; It's not really needed but it might help simplify some things. ; ;(drn (bitfield mode src start length) ; ... ; ... ;) ;; Integer conversions. (drn (ext &options &mode s1) #f (OPTIONS ANYINTMODE RTX) (NA NA ANY) UNARY #f ) (drn (zext &options &mode s1) #f (OPTIONS ANYINTMODE RTX) (NA NA ANY) UNARY #f ) (drn (trunc &options &mode s1) #f (OPTIONS ANYINTMODE RTX) (NA NA ANY) UNARY #f ) ;; Conversions involving floating point values. (drn (fext &options &mode how s1) #f (OPTIONS ANYFLOATMODE RTX RTX) (NA NA INT ANY) UNARY #f ) (drn (ftrunc &options &mode how s1) #f (OPTIONS ANYFLOATMODE RTX RTX) (NA NA INT ANY) UNARY #f ) (drn (float &options &mode how s1) #f (OPTIONS ANYFLOATMODE RTX RTX) (NA NA INT ANY) UNARY #f ) (drn (ufloat &options &mode how s1) #f (OPTIONS ANYFLOATMODE RTX RTX) (NA NA INT ANY) UNARY #f ) (drn (fix &options &mode how s1) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA INT ANY) UNARY #f ) (drn (ufix &options &mode how s1) #f (OPTIONS ANYINTMODE RTX RTX) (NA NA INT ANY) UNARY #f ) ; Comparisons. ; MODE is the mode of S1,S2. The result always has mode BI. (drn (eq &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (ne &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) ; ??? In non-sim case, ensure s1,s2 is in right C type for right result. (drn (lt &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (le &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (gt &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (ge &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) ; ??? In non-sim case, ensure s1,s2 is in right C type for right result. (drn (ltu &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (leu &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (gtu &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) (drn (geu &options &mode s1 s2) BI (OPTIONS ANYNUMMODE RTX RTX) (NA NA MATCHEXPR MATCH2) COMPARE #f ) ; Set membership. ; Useful in ifield assertions. ; Return a boolean (BI mode) indicating if VALUE is in SET. ; VALUE is any constant rtx. SET is a `number-list' rtx. (drn (member &options &mode value set) #f (OPTIONS BIMODE RTX RTX) (NA NA INT INT) MISC (begin (if (not (rtx-constant? value)) (estate-error *estate* "`member rtx'" "value is not a constant" value)) (if (not (rtx-kind? 'number-list set)) (estate-error *estate* "`member' rtx" "set is not a `number-list' rtx" set)) (if (memq (rtx-constant-value value) (rtx-number-list-values set)) (rtx-true) (rtx-false))) ) ;; FIXME: "number" in "number-list" implies floats are ok. ;; Rename to integer-list, int-list, or some such. (drn (number-list &options &mode value-list) #f (OPTIONS INTMODE NUMBER . NUMBER) (NA NA NA . NA) MISC #f ) ; Conditional execution. ; FIXME: make syntax node? (drn (if &options &mode cond then . else) #f ;; ??? It would be cleaner if TESTRTX had to have BI mode. (OPTIONS ANYEXPRMODE TESTRTX RTX . RTX) (NA NA ANYINT MATCHEXPR . MATCH3) IF (apply e-if (append! (list *estate* mode cond then) else)) ) ; ??? The syntax here isn't quite that of Scheme. A condition must be ; followed by a result expression. ; ??? The syntax here isn't quite right, there must be at least one cond rtx. ; ??? Intermediate expressions (the ones before the last one) needn't have ; the same mode as the result. (drsn (cond &options &mode . cond-code-list) #f (OPTIONS ANYEXPRMODE . CONDRTX) (NA NA . MATCHEXPR) COND #f ) ; ??? The syntax here isn't quite right, there must be at least one case. ; ??? Intermediate expressions (the ones before the last one) needn't have ; the same mode as the result. (drn (case &options &mode test . case-list) #f (OPTIONS ANYEXPRMODE RTX . CASERTX) (NA NA ANY . MATCHEXPR) COND #f ) ; parallel, sequence, do-count, closure ; This has to be a syntax node as we don't want EXPRS to be pre-evaluated. ; All semantic ops must have a mode, though here it must be VOID. ; IGNORE is for consistency with sequence. ??? Delete some day. ; ??? There's no real need for mode either, but convention requires it. (drsn (parallel &options &mode ignore expr . exprs) #f (OPTIONS VOIDMODE LOCALS RTX . RTX) (NA NA NA VOID . VOID) SEQUENCE #f ) ; 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. (drsn (sequence &options &mode locals expr . exprs) #f (OPTIONS VOIDORNUMMODE LOCALS RTX . RTX) (NA NA NA MATCHSEQ . MATCHSEQ) SEQUENCE #f ) ; This has to be a syntax node to handle iter-var properly: it's not defined ; yet and thus pre-evaluating the expressions doesn't work. (drsn (do-count &options &mode iter-var nr-times expr . exprs) #f (OPTIONS VOIDMODE ITERATION RTX RTX . RTX) (NA NA NA INT VOID . VOID) SEQUENCE #f ) ; Internal rtx to create a closure. ; 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 isa-name-list env-stack expr) #f (OPTIONS VOIDORNUMMODE SYMBOLLIST ENVSTACK RTX) (NA NA NA NA MATCHEXPR) MISC #f ) )) ; End of def-rtx-funcs