OpenCores
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
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.