URL
https://opencores.org/ocsvn/scarts/scarts/trunk
Subversion Repositories scarts
[/] [scarts/] [trunk/] [toolchain/] [scarts-binutils/] [binutils-2.19.1/] [cgen/] [rtl-c.scm] - Rev 6
Compare with Previous | Blame | View Log
; RTL->C translation support. ; Copyright (C) 2000, 2005, 2009 Red Hat, Inc. ; This file is part of CGEN. ; See file COPYING.CGEN for details. ; Generating C from RTL ; --------------------- ; The main way to generate C code from an RTL expression is: ; ; (rtl-c mode '(func mode ...) nil) ; ; E.g. ; (rtl-c DFLT '(add SI (const SI 1) (const SI 2)) nil) ; --> ; "ADDSI (1, 2)" ; Mode `DFLT' (DEFAULTmode) means "use the default/natural mode". ; ; The expression is in source form or may be already compiled (with ; rtx-compile). ; ; The `set' rtx needs to be handled a little carefully. ; Both the dest and src are processed first, and then code to perform the ; assignment is computed. However, the dest may require more than a simple ; C assignment. Therefore set dests are converted to the specified object ; (e.g. a hardware operand) and then a message is sent to this object to ; perform the actual code generation. ; ; All interesting operands (e.g. regs, mem) are `operand' objects. ; The following messages must be supported by operand objects. ; - get-mode - return mode of operand ; - cxmake-get - return <c-expr> object containing operand's value ; - gen-set-quiet - return string of C code to set operand's value (no tracing) ; - gen-set-trace - return string of C code to set operand's value ; ; Instruction fields are refered to by name. ; (estate-owner estate) must be an instruction that has the field. ; Instruction ifields must have these methods: ; - get-mode ; - cxmake-get ; ; Conventions used in this file: ; - see rtl.scm ; The <c-expr> object. ; This is a fully translated expression (i.e. C code). ; The mode of C-CODE. ; The translated C code. ; The source expression, for debugging. ; Attributes of the expression. ; List of temporaries required to compute the expression. ; ??? wip. These would be combined as the expression is ; built up. Then in sets and other statements, the temporaries ; would be declared. ;(tmps . nil) ; FIXME: Extend COS to allow specifying member predicates. ;(assert (atlist? atlist)) ; FIXME: What should this be? ; Accessor fns ;(define cx:tmps (elm-make-getter <c-expr> 'tmps)) ; Any object with attributes requires the get-atlist method. ; Respond to 'get-mode messages. ; Respond to 'get-name messages for rtx-dump. "("") "; Return C code to perform an assignment. ; NEWVAL is a <c-expr> object of the value to be assigned to SELF. " "" = "";\n"" "" = "";\n"; Return the C code of CX. ; ??? This used to handle lazy evaluation of the expression. ; Maybe it will again, so it's left in, as a cover fn to cx:c-code. ; Main routine to create a <c-expr> node object. ; MODE is either the mode's symbol (e.g. 'QI) or a mode object. ; CODE is a string of C code. ; Make copy of CX in new mode MODE. ; MODE must be a <mode> object. ; Same as cx:make except with attributes. ; Return a boolean indicated if X is a <c-expr> object. ; RTX environment support. " "" = "";\n"" "" = "";\n"" "" "";\n"; Top level routines to handle rtl->c translation. ; rtl->c configuration parameters ; #t -> emit calls to rtl cover fns, otherwise emit plain C where possible. ; Called before emitting code to configure the generator. ; ??? I think this can go away now (since cover-fn specification is also ; done at each call to rtl-c). ; done "rtl-c-config: unknown option:"; Subclass of <eval-state> to record additional things needed for rtl->c. ; #t -> emit calls to rtl cover fns. ; name of output language, "c" or "c++" "c"; #t if generating code for a macro. ; Each newline is then preceeded with '\\'. ; #f -> reference ifield values using FLD macro. ; #t -> use C variables. ; ??? This is only needed to get correct ifield references ; in opcodes, decoder, and semantics. Maybe a better way to ; go would be to specify the caller's name so there'd be just ; one of these, rather than an increasing number. However, ; for now either way is the same. ; An alternative is to specify a callback to try first. ; FIXME: involves upcasting. ; Return booleans indicating if output language is C/C++. "c""c++"; Initialize parent class first. ; ??? Could invoke method to initialize here. ; Build in reverse order, as we reverse it back when we're done. ; Build an estate for use in generating C. ; CONTEXT is a <context> object or #f if there is none. ; OWNER is the owner of the expression or #f if there is none. ; 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. ; FIXME: context ; FIXME: owner ; macro? ; Translate RTL expression EXPR to C. ; ESTATE is the current rtx evaluation state. ; Translate parsed RTL expression X to a string of C code. ; X must have already been fed through rtx-parse/rtx-compile. ; MODE is the desired mode of the value or DFLT for "natural mode". ; 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. ; ??? Maybe EXTRA-VARS-ALIST should be handled this way. ; Same as rtl-c-parsed but X is unparsed. ; ??? rtx-compile could return a closure, then we wouldn't have to ; pass EXTRA-VARS-ALIST to two routines here. ; Same as rtl-c-with-estate except return a <c-expr> object. ; Same as rtl-c-parsed except return a <c-expr> object. ; Same as rtl-c-expr-parsed but X is unparsed. ; ??? rtx-compile could return a closure, then we wouldn't have to ; pass EXTRA-VARS-ALIST to two routines here. ; 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. ; FIXME: context ; FIXME: owner ; macro? "c++"; Translate parsed RTL expression X to a string of C++ code. ; X must have already been fed through rtx-parse/rtx-compile. ; MODE is the desired mode of the value or DFLT for "natural mode". ; 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. ; ??? Maybe EXTRA-VARS-ALIST should be handled this way. ; Same as rtl-c-parsed but X is unparsed. ; ??? rtx-compile could return a closure, then we wouldn't have to ; pass EXTRA-VARS-ALIST to two routines here. ; Top level routines for getting/setting values. ; Return a <c-expr> node to get the value of SRC in mode MODE. ; ESTATE is the current rtl evaluation state. ; SRC is one of: ; - <c-expr> node ; - rtl expression (e.g. '(add WI dr sr)) ; - sequence's local variable name ; - sequence's local variable object ; - operand name ; - operand object ; - a string of C code ; FIXME: Reduce acceptable values of SRC. ; The result has mode MODE, unless MODE is the "default mode indicator" ; (DFLT) in which case the mode of the result is derived from SRC. ; If SRC is a string, MODE can't be VOID or DFLT. ; ; ??? mode compatibility checks are wip "incompatible mode for ""("" vs "") in ""\"""\""": "; The recursive call to -rtl-c-get is in case the result of rtx-eval ; is a hardware object, rtx-func object, or another rtl expression. ; There must have been some change, otherwise we'll loop forever. ; FIXME: If we fetch the mode here, operands can assume ; they never get called with "default mode". "operand "" referenced in incompatible mode: ""sequence temp "" referenced in incompatible mode: "; Default mode of string argument is INT. ; Default mode of string argument is INT. "-rtl-c-get: invalid argument:""(rtl-c-get "" "")\n""(rtl-c-get "" "") => ""\n"; Return a <c-expr> object to set the value of DEST to SRC. ; ESTATE is the current rtl evaluation state. ; DEST is one of: ; - <c-expr> node ; - rtl expression (e.g. '(mem QI dr)) ; SRC is a <c-expr> object. ; The mode of the result is always VOID (void). ;(display (list 'rtl-c-set-quiet mode dest src)) (newline) "rtl-c-set-quiet: invalid dest:""rtl-c-set-quiet: invalid dest:"; Same as rtl-c-set-quiet except also print TRACE_RESULT message. ; ??? One possible change is to defer the (rtl-c-get src) call to dest's ; set handler. Such sources would be marked accordingly and rtl-c-get ; would recognize them. This would allow, for example, passing the address ; of the result to the computation. ;(display (list 'rtl-c-set-trace mode dest src)) (newline) "rtl-c-set-trace: invalid dest:""rtl-c-set-trace: invalid dest:"; FIXME: internal routines ; Emit C code for each rtx function. ; Table mapping rtx function to C generator. ; Return the C generator for <rtx-func> F. ; Support for explicit C/C++ code. ; ??? Actually, "support for explicit foreign language code". ; s-c-call needs a better name but "unspec" seems like obfuscation. ; ??? Need to distinguish owner of call (cpu, ???). "current_cpu->"" ("; FIXME: Prepend @cpu@_ to name here, and delete @cpu@_ from ; description file. " (current_cpu"", "; If the mode is VOID, this is a statement. ; Otherwise it's an expression. ; ??? Bad assumption! VOID expressions may be used ; within sequences without local vars, which are translated ; to comma-expressions. ");\n"")"; Same as c-call except there is no particular owner of the call. ; In general this means making a call to a non-member function, ; whereas c-call makes calls to member functions (in C++ parlance). " ("", "; If the mode is VOID, this is a statement. ; Otherwise it's an expression. ; ??? Bad assumption! VOID expressions may be used ; within sequences without local vars, which are translated ; to comma-expressions. ");\n"")"; Standard arithmetic operations. ; Return a boolean indicating if a cover function/macro should be emitted ; to perform an operation. ; C-OP is a string containing the C operation or #f if there is none. ; MODE is the mode of the operation. ; If no C operation has been provided, use a macro, or ; if this is the simulator and MODE is not a host mode, use a macro. ; (or (not c-op) ; (and (estate-rtl-cover-fns? estate) ; (not (mode:host? mode)))) ; FIXME: The current definition is a temporary hack while host/target-ness ; of INT/UINT is unresolved. ; One operand referenced, result is in same mode. ; Refetch mode in case it was DFLT and ensure unsigned->signed. ; FIXME: Argument checking. "CGEN_CPU_FPU (current_cpu)->ops->"" (CGEN_CPU_FPU (current_cpu), "")"" ("")"; not sem-mode on purpose "("" (""))"; Two operands referenced in the same mode producing a result in the same mode. ; If MODE is DFLT, use the mode of SRC1. ; ; ??? Will eventually want to handle floating point modes specially. Since ; bigger modes may get clumsily passed (there is no pass by reference in C) and ; since we want to eventually handle lazy transformation, FP values could be ; passed by reference. This is easy in C++. C requires more work and is ; defered until it's warranted. ; Implementing this should probably be via a new cxmake-get-ref method, ; rather then complicating cxmake-get. Ditto for rtl-c-get-ref/rtl-c-get. ; Refetch mode in case it was DFLT and ensure unsigned->signed. ; FIXME: Argument checking. "CGEN_CPU_FPU (current_cpu)->ops->"" (CGEN_CPU_FPU (current_cpu), "", "")"" ("", "")"; not sem-mode on purpose "(("") "" (""))"; Same as s-binop except there's a third argument which is always one bit. ; Refetch mode in case it was DFLT and ensure unsigned->signed. ; FIXME: Argument checking. " ("", "", "")"; Shift operations are slightly different than binary operations: ; the mode of src2 is any integral mode. ; ??? Note that some cpus have a signed shift left that is semantically ; different from a logical one. May need to create `sla' some day. Later. ; Refetch mode in case it was DFLT and ensure unsigned->signed ; [sign of operation is determined from operation name, not mode]. ; FIXME: Argument checking. " ("", "")"; not sem-mode on purpose "("; Ensure correct sign of shift. "SRL""(""""unsigned "") ""SRA""("") """"("") "" (""))"; Process andif, orif. ; SRC1 and SRC2 have any arithmetic mode. ; The result has mode BI. ; ??? May want to use INT as BI may introduce some slowness ; in the generated code. ; FIXME: Argument checking. ; If this is the simulator and MODE is not a host mode, use a macro. ; ??? MODE here being the mode of SRC1. Maybe later. ; "BI", leave off mode, no need for it " ("", "")""(("") "" (""))"; Mode conversions. ; Get S1 in its normal mode, then convert. "(("")"" ("")"" (""))""CGEN_CPU_FPU (current_cpu)->ops->"" (CGEN_CPU_FPU (current_cpu), "")"" ("")"; Compare SRC1 and SRC2 in mode MODE. The result has mode BI. ; NAME is one of eq,ne,lt,le,gt,ge,ltu,leu,gtu,geu. ; ??? May want a host int mode result as BI may introduce some slowness ; in the generated code. ; Refetch mode in case it was DFLT. ; FIXME: Argument checking. ; If no C operation has been provided, use a macro, or ; if this is the simulator and MODE is not a host mode, use a macro. "CGEN_CPU_FPU (current_cpu)->ops->"" (CGEN_CPU_FPU (current_cpu), "", "")"" ("", "")""(("") "" (""))"; Conditional execution. ; `if' in RTL has a result, like ?: in C. ; We support both: one with a result (non VOID mode), and one without (VOID mode). ; The non-VOID case must have an else part. ; MODE is the mode of the result, not the comparison. ; The comparison is expected to return a zero/non-zero value. ; ??? Perhaps this should be a syntax-expr. Later. "if: too many elements in `else' part""if ("")"" {\n""}"" else {\n""}\n""\n""(("") ? ("") : (""))""non-void-mode `if' must have `else' part"; A multiway `if'. ; If MODE is VOID emit a series of if/else's. ; If MODE is not VOID, emit a series of ?:'s. ; COND-CODE-LIST is a list of lists, each sublist is a list of two elements: ; condition, code. The condition part must return a zero/non-zero value, and ; the code part is treated as a `sequence'. ; This defer argument evaluation, the syntax ; ((... condition ...) ... action ...) ; needs special parsing. ; FIXME: Need more error checking of arguments. "empty `cond'""if (""("") "") ? "" else if ("" : ("" else "" : """")"; Utility of s-case to print a case prefix (for lack of a better term). " case "; yes, upcase "case:""bad case"" : "; Utility of s-case to handle a void result. " switch ("")\n"" {\n"" default : "" break;\n"" }\n"; Utility of s-case-non-vm to generate code to perform the test. """symbol not an enum""invalid case"""" || "" == "; Utility of s-case to handle a non-void result. ; This is expanded as a series of ?:'s. "("") ? "" : ("" : "")"; C switch statement ; To follow convention, MODE is the first arg. ; FIXME: What to allow for case choices is wip. ; Parallels and Sequences ; Temps for `parallel' are recorded differently than for `sequence'. ; ??? I believe this is because there was an interaction between the two. ; Record a temporary needed for a parallel in mode MODE. ; We just need to record the mode with a unique name so we use a <c-expr> ; object where the "expression" is the variable's name. "temp"; Return the next temp from the list, and leave the list pointing to the ; next one. ;(display temp-list) (newline) " "; ??? mode:c-type " "";""\n"; Parallels are handled by converting them into two sequences. The first has ; all set destinations replaced with temps, and the second has all set sources ; replaced with those temps. ; ??? Revisit later to see if (if ...) and (set pc ...) is ok. ; How about disallowing if's and jump's inside parallels? ; One can still put a parallel inside an `if' however. ; replace dest with temp ; This must process expressions in the same order as -par-replace-set-dests! ; the source's temp ; Return a <c-expr> node for a `parallel'. ; Initialize -par-temp-list for -par-replace-set-dests. ; Initialize -par-temp-list for -par-replace-set-srcs. ; FIXME: do {} while (0); doesn't get "optimized out" ; internally by gcc, meaning two labels and a loop are ; created for it to have to process. We can generate pretty ; big files and can cause gcc to require *lots* of memory. ; So let's try just {} ... "{\n""}\n"; Return a <c-expr> node for a `sequence'. ; compile env ; FIXME: do {} while (0); doesn't get "optimized out" ; internally by gcc, meaning two labels and a loop are ; created for it to have to process. We can generate pretty ; big files and can cause gcc to require *lots* of memory. ; So let's try just {} ... "{\n""}\n"; Don't use GCC extension unless necessary. "(""({ "", ""; "; Strip off gratuitous ";\n" at end of expressions that ; misguessed themselves to be in statement context. ; See s-c-call, s-c-call-raw above. ";\n"")""; })"; Return a <c-expr> node for a `do-count'. "{\n"" "" = "";\n"" for ("" = 0;\n"" "" < "";\n"" ++"")\n"" {\n"" }\n""}\n"; ***************************************************************************** ; ; RTL->C generators for each rtx function. ; Return code to set FN as the generator for RTX. ; The rest of this file is one big function to return the rtl->c lookup table. ; Error generation "cgen_rtx_error""\"""\"""\"""("", 0)"; Enum support ; Instruction field support. ; ??? This should build an operand object like -build-ifield-operand! does ; in semantics.scm. ; ??? Mode support is wip. "FLD ("")"; (let ((f (current-ifld-lookup ifld-name))) ; (make <operand> (obj-location f) ifld-name ifld-name ; (atlist-cons (bool-attr-make 'SEM-ONLY #t) ; (obj-atlist f)) ; (obj:name (ifld-hw-type f)) ; (obj:name (ifld-mode f)) ; (make <hw-index> 'anonymous ; 'ifield (ifld-mode f) f) ; nil #f #f)) ; Operand support "undefined operand""bad arg to `operand'";; if we're looking at an operand inside a (delay ...) rtx, then we ;; are talking about a _delayed_ operand, which is a different ;; beast. rather than try to work out what context we were ;; constructed within, we just clone the operand instance and set ;; the new one to have a delayed value. the setters and getters ;; will work it out. ;; else return the normal object "undefined local""bad arg to `local'""ref: not processing an insn""(referenced & (1 << ""))"; ??? Maybe this should return an operand object. "; /*clobber*/\n";; FIXME: Try to move SID stuff into sid-foo.scm. ;; check for proper usage "(delay ...) rtx applied to wrong type of operand, should be pc, register or memory";; signal an error if we're delayed and not in a "parallel-insns" CPU "delayed operand in a non-parallel cpu";; update cpu-global pipeline bound ;; pass along new delay to embedded rtx ;; not in sid-land ; Gets expanded as a macro. ;(define-fn annul (estate yes?) ; (s-c-call estate 'VOID "SEM_ANNUL_INSN" "pc" yes?) ;) ;(s-c-call estate 'VOID "SEM_SKIP_INSN" "pc" yes?) "(GET_ATTR ("") == "")""GET_ATTR""attr: unsupported object type:""MAKEDI ("", "")"; ??? GCC complains if not affixed with "U" but that's not k&r. ;(string-append (number->string val) "U")) "0x"; Else punt. ; FIXME: Endianness issues undecided. ; FIXME: Ensure correct number of args for in/out modes. ; Ensure compatible modes. "JOIN"; Refetch mode in case it was DFLT. "SUBWORD"" ("", """")""((void) 0); /*nop*/\n""NEG""-""ABS""INV""~""NOT""!""ADD""+""SUB""-""ADDC";; ??? Whether to rename ADDCF/ADDOF -> ADDCCF/ADDCOF is debatable. "ADDCF""ADDOF""SUBC";; ??? Whether to rename SUBCF/SUBOF -> SUBCCF/SUBCOF is debatable. "SUBCF""SUBOF";; ??? These are deprecated. Delete in time. "ADDCF""ADDOF""SUBCF""SUBOF";(define-fn zflag (estate options mode value) ; (list 'eq mode value (list 'const mode 0)) ;) ;(define-fn nflag (estate options mode value) ; (list 'lt mode value (list 'const mode 0)) ;) "MUL""*""DIV""/""UDIV""/""MOD""%""UMOD""%""SQRT""COS""SIN""MIN""MAX""UMIN""UMAX""AND""&""OR""|""XOR""^""SLL""<<""SRL"">>""SRA"">>""ROR""ROL""ANDIF""&&""ORIF""||""EXT""ZEXT""TRUNC""FEXT""FTRUNC""FLOAT""UFLOAT""FIX""UFIX""==""!=""<""<="">"">=""<""<="">"">="; FIXME: Multiple evalutions of VALUE. "("" == "")""("")"" || ("" == "")"; ??? estate-push-env? ; The result is the rtl->c generator table. ; End of rtl-c-build-table