mirror of
https://github.com/pmret/gcc-papermario.git
synced 2024-11-08 11:53:01 +01:00
1011 lines
44 KiB
Plaintext
1011 lines
44 KiB
Plaintext
|
This is Info file gcc.info, produced by Makeinfo version 1.67 from the
|
|||
|
input file gcc.texi.
|
|||
|
|
|||
|
This file documents the use and the internals of the GNU compiler.
|
|||
|
|
|||
|
Published by the Free Software Foundation 59 Temple Place - Suite 330
|
|||
|
Boston, MA 02111-1307 USA
|
|||
|
|
|||
|
Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
|
|||
|
Free Software Foundation, Inc.
|
|||
|
|
|||
|
Permission is granted to make and distribute verbatim copies of this
|
|||
|
manual provided the copyright notice and this permission notice are
|
|||
|
preserved on all copies.
|
|||
|
|
|||
|
Permission is granted to copy and distribute modified versions of
|
|||
|
this manual under the conditions for verbatim copying, provided also
|
|||
|
that the sections entitled "GNU General Public License," "Funding for
|
|||
|
Free Software," and "Protect Your Freedom--Fight `Look And Feel'" are
|
|||
|
included exactly as in the original, and provided that the entire
|
|||
|
resulting derived work is distributed under the terms of a permission
|
|||
|
notice identical to this one.
|
|||
|
|
|||
|
Permission is granted to copy and distribute translations of this
|
|||
|
manual into another language, under the above conditions for modified
|
|||
|
versions, except that the sections entitled "GNU General Public
|
|||
|
License," "Funding for Free Software," and "Protect Your Freedom--Fight
|
|||
|
`Look And Feel'", and this permission notice, may be included in
|
|||
|
translations approved by the Free Software Foundation instead of in the
|
|||
|
original English.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Regs and Memory, Next: Arithmetic, Prev: Constants, Up: RTL
|
|||
|
|
|||
|
Registers and Memory
|
|||
|
====================
|
|||
|
|
|||
|
Here are the RTL expression types for describing access to machine
|
|||
|
registers and to main memory.
|
|||
|
|
|||
|
`(reg:M N)'
|
|||
|
For small values of the integer N (those that are less than
|
|||
|
`FIRST_PSEUDO_REGISTER'), this stands for a reference to machine
|
|||
|
register number N: a "hard register". For larger values of N, it
|
|||
|
stands for a temporary value or "pseudo register". The compiler's
|
|||
|
strategy is to generate code assuming an unlimited number of such
|
|||
|
pseudo registers, and later convert them into hard registers or
|
|||
|
into memory references.
|
|||
|
|
|||
|
M is the machine mode of the reference. It is necessary because
|
|||
|
machines can generally refer to each register in more than one
|
|||
|
mode. For example, a register may contain a full word but there
|
|||
|
may be instructions to refer to it as a half word or as a single
|
|||
|
byte, as well as instructions to refer to it as a floating point
|
|||
|
number of various precisions.
|
|||
|
|
|||
|
Even for a register that the machine can access in only one mode,
|
|||
|
the mode must always be specified.
|
|||
|
|
|||
|
The symbol `FIRST_PSEUDO_REGISTER' is defined by the machine
|
|||
|
description, since the number of hard registers on the machine is
|
|||
|
an invariant characteristic of the machine. Note, however, that
|
|||
|
not all of the machine registers must be general registers. All
|
|||
|
the machine registers that can be used for storage of data are
|
|||
|
given hard register numbers, even those that can be used only in
|
|||
|
certain instructions or can hold only certain types of data.
|
|||
|
|
|||
|
A hard register may be accessed in various modes throughout one
|
|||
|
function, but each pseudo register is given a natural mode and is
|
|||
|
accessed only in that mode. When it is necessary to describe an
|
|||
|
access to a pseudo register using a nonnatural mode, a `subreg'
|
|||
|
expression is used.
|
|||
|
|
|||
|
A `reg' expression with a machine mode that specifies more than
|
|||
|
one word of data may actually stand for several consecutive
|
|||
|
registers. If in addition the register number specifies a
|
|||
|
hardware register, then it actually represents several consecutive
|
|||
|
hardware registers starting with the specified one.
|
|||
|
|
|||
|
Each pseudo register number used in a function's RTL code is
|
|||
|
represented by a unique `reg' expression.
|
|||
|
|
|||
|
Some pseudo register numbers, those within the range of
|
|||
|
`FIRST_VIRTUAL_REGISTER' to `LAST_VIRTUAL_REGISTER' only appear
|
|||
|
during the RTL generation phase and are eliminated before the
|
|||
|
optimization phases. These represent locations in the stack frame
|
|||
|
that cannot be determined until RTL generation for the function
|
|||
|
has been completed. The following virtual register numbers are
|
|||
|
defined:
|
|||
|
|
|||
|
`VIRTUAL_INCOMING_ARGS_REGNUM'
|
|||
|
This points to the first word of the incoming arguments
|
|||
|
passed on the stack. Normally these arguments are placed
|
|||
|
there by the caller, but the callee may have pushed some
|
|||
|
arguments that were previously passed in registers.
|
|||
|
|
|||
|
When RTL generation is complete, this virtual register is
|
|||
|
replaced by the sum of the register given by
|
|||
|
`ARG_POINTER_REGNUM' and the value of `FIRST_PARM_OFFSET'.
|
|||
|
|
|||
|
`VIRTUAL_STACK_VARS_REGNUM'
|
|||
|
If `FRAME_GROWS_DOWNWARD' is defined, this points to
|
|||
|
immediately above the first variable on the stack.
|
|||
|
Otherwise, it points to the first variable on the stack.
|
|||
|
|
|||
|
`VIRTUAL_STACK_VARS_REGNUM' is replaced with the sum of the
|
|||
|
register given by `FRAME_POINTER_REGNUM' and the value
|
|||
|
`STARTING_FRAME_OFFSET'.
|
|||
|
|
|||
|
`VIRTUAL_STACK_DYNAMIC_REGNUM'
|
|||
|
This points to the location of dynamically allocated memory
|
|||
|
on the stack immediately after the stack pointer has been
|
|||
|
adjusted by the amount of memory desired.
|
|||
|
|
|||
|
This virtual register is replaced by the sum of the register
|
|||
|
given by `STACK_POINTER_REGNUM' and the value
|
|||
|
`STACK_DYNAMIC_OFFSET'.
|
|||
|
|
|||
|
`VIRTUAL_OUTGOING_ARGS_REGNUM'
|
|||
|
This points to the location in the stack at which outgoing
|
|||
|
arguments should be written when the stack is pre-pushed
|
|||
|
(arguments pushed using push insns should always use
|
|||
|
`STACK_POINTER_REGNUM').
|
|||
|
|
|||
|
This virtual register is replaced by the sum of the register
|
|||
|
given by `STACK_POINTER_REGNUM' and the value
|
|||
|
`STACK_POINTER_OFFSET'.
|
|||
|
|
|||
|
`(subreg:M REG WORDNUM)'
|
|||
|
`subreg' expressions are used to refer to a register in a machine
|
|||
|
mode other than its natural one, or to refer to one register of a
|
|||
|
multi-word `reg' that actually refers to several registers.
|
|||
|
|
|||
|
Each pseudo-register has a natural mode. If it is necessary to
|
|||
|
operate on it in a different mode--for example, to perform a
|
|||
|
fullword move instruction on a pseudo-register that contains a
|
|||
|
single byte--the pseudo-register must be enclosed in a `subreg'.
|
|||
|
In such a case, WORDNUM is zero.
|
|||
|
|
|||
|
Usually M is at least as narrow as the mode of REG, in which case
|
|||
|
it is restricting consideration to only the bits of REG that are
|
|||
|
in M.
|
|||
|
|
|||
|
Sometimes M is wider than the mode of REG. These `subreg'
|
|||
|
expressions are often called "paradoxical". They are used in
|
|||
|
cases where we want to refer to an object in a wider mode but do
|
|||
|
not care what value the additional bits have. The reload pass
|
|||
|
ensures that paradoxical references are only made to hard
|
|||
|
registers.
|
|||
|
|
|||
|
The other use of `subreg' is to extract the individual registers of
|
|||
|
a multi-register value. Machine modes such as `DImode' and
|
|||
|
`TImode' can indicate values longer than a word, values which
|
|||
|
usually require two or more consecutive registers. To access one
|
|||
|
of the registers, use a `subreg' with mode `SImode' and a WORDNUM
|
|||
|
that says which register.
|
|||
|
|
|||
|
Storing in a non-paradoxical `subreg' has undefined results for
|
|||
|
bits belonging to the same word as the `subreg'. This laxity makes
|
|||
|
it easier to generate efficient code for such instructions. To
|
|||
|
represent an instruction that preserves all the bits outside of
|
|||
|
those in the `subreg', use `strict_low_part' around the `subreg'.
|
|||
|
|
|||
|
The compilation parameter `WORDS_BIG_ENDIAN', if set to 1, says
|
|||
|
that word number zero is the most significant part; otherwise, it
|
|||
|
is the least significant part.
|
|||
|
|
|||
|
Between the combiner pass and the reload pass, it is possible to
|
|||
|
have a paradoxical `subreg' which contains a `mem' instead of a
|
|||
|
`reg' as its first operand. After the reload pass, it is also
|
|||
|
possible to have a non-paradoxical `subreg' which contains a
|
|||
|
`mem'; this usually occurs when the `mem' is a stack slot which
|
|||
|
replaced a pseudo register.
|
|||
|
|
|||
|
Note that it is not valid to access a `DFmode' value in `SFmode'
|
|||
|
using a `subreg'. On some machines the most significant part of a
|
|||
|
`DFmode' value does not have the same format as a single-precision
|
|||
|
floating value.
|
|||
|
|
|||
|
It is also not valid to access a single word of a multi-word value
|
|||
|
in a hard register when less registers can hold the value than
|
|||
|
would be expected from its size. For example, some 32-bit
|
|||
|
machines have floating-point registers that can hold an entire
|
|||
|
`DFmode' value. If register 10 were such a register `(subreg:SI
|
|||
|
(reg:DF 10) 1)' would be invalid because there is no way to
|
|||
|
convert that reference to a single machine register. The reload
|
|||
|
pass prevents `subreg' expressions such as these from being formed.
|
|||
|
|
|||
|
The first operand of a `subreg' expression is customarily accessed
|
|||
|
with the `SUBREG_REG' macro and the second operand is customarily
|
|||
|
accessed with the `SUBREG_WORD' macro.
|
|||
|
|
|||
|
`(scratch:M)'
|
|||
|
This represents a scratch register that will be required for the
|
|||
|
execution of a single instruction and not used subsequently. It is
|
|||
|
converted into a `reg' by either the local register allocator or
|
|||
|
the reload pass.
|
|||
|
|
|||
|
`scratch' is usually present inside a `clobber' operation (*note
|
|||
|
Side Effects::.).
|
|||
|
|
|||
|
`(cc0)'
|
|||
|
This refers to the machine's condition code register. It has no
|
|||
|
operands and may not have a machine mode. There are two ways to
|
|||
|
use it:
|
|||
|
|
|||
|
* To stand for a complete set of condition code flags. This is
|
|||
|
best on most machines, where each comparison sets the entire
|
|||
|
series of flags.
|
|||
|
|
|||
|
With this technique, `(cc0)' may be validly used in only two
|
|||
|
contexts: as the destination of an assignment (in test and
|
|||
|
compare instructions) and in comparison operators comparing
|
|||
|
against zero (`const_int' with value zero; that is to say,
|
|||
|
`const0_rtx').
|
|||
|
|
|||
|
* To stand for a single flag that is the result of a single
|
|||
|
condition. This is useful on machines that have only a
|
|||
|
single flag bit, and in which comparison instructions must
|
|||
|
specify the condition to test.
|
|||
|
|
|||
|
With this technique, `(cc0)' may be validly used in only two
|
|||
|
contexts: as the destination of an assignment (in test and
|
|||
|
compare instructions) where the source is a comparison
|
|||
|
operator, and as the first operand of `if_then_else' (in a
|
|||
|
conditional branch).
|
|||
|
|
|||
|
There is only one expression object of code `cc0'; it is the value
|
|||
|
of the variable `cc0_rtx'. Any attempt to create an expression of
|
|||
|
code `cc0' will return `cc0_rtx'.
|
|||
|
|
|||
|
Instructions can set the condition code implicitly. On many
|
|||
|
machines, nearly all instructions set the condition code based on
|
|||
|
the value that they compute or store. It is not necessary to
|
|||
|
record these actions explicitly in the RTL because the machine
|
|||
|
description includes a prescription for recognizing the
|
|||
|
instructions that do so (by means of the macro
|
|||
|
`NOTICE_UPDATE_CC'). *Note Condition Code::. Only instructions
|
|||
|
whose sole purpose is to set the condition code, and instructions
|
|||
|
that use the condition code, need mention `(cc0)'.
|
|||
|
|
|||
|
On some machines, the condition code register is given a register
|
|||
|
number and a `reg' is used instead of `(cc0)'. This is usually the
|
|||
|
preferable approach if only a small subset of instructions modify
|
|||
|
the condition code. Other machines store condition codes in
|
|||
|
general registers; in such cases a pseudo register should be used.
|
|||
|
|
|||
|
Some machines, such as the Sparc and RS/6000, have two sets of
|
|||
|
arithmetic instructions, one that sets and one that does not set
|
|||
|
the condition code. This is best handled by normally generating
|
|||
|
the instruction that does not set the condition code, and making a
|
|||
|
pattern that both performs the arithmetic and sets the condition
|
|||
|
code register (which would not be `(cc0)' in this case). For
|
|||
|
examples, search for `addcc' and `andcc' in `sparc.md'.
|
|||
|
|
|||
|
`(pc)'
|
|||
|
This represents the machine's program counter. It has no operands
|
|||
|
and may not have a machine mode. `(pc)' may be validly used only
|
|||
|
in certain specific contexts in jump instructions.
|
|||
|
|
|||
|
There is only one expression object of code `pc'; it is the value
|
|||
|
of the variable `pc_rtx'. Any attempt to create an expression of
|
|||
|
code `pc' will return `pc_rtx'.
|
|||
|
|
|||
|
All instructions that do not jump alter the program counter
|
|||
|
implicitly by incrementing it, but there is no need to mention
|
|||
|
this in the RTL.
|
|||
|
|
|||
|
`(mem:M ADDR)'
|
|||
|
This RTX represents a reference to main memory at an address
|
|||
|
represented by the expression ADDR. M specifies how large a unit
|
|||
|
of memory is accessed.
|
|||
|
|
|||
|
`(addressof:M REG)'
|
|||
|
This RTX represents a request for the address of register REG.
|
|||
|
Its mode is always `Pmode'. If there are any `addressof'
|
|||
|
expressions left in the function after CSE, REG is forced into the
|
|||
|
stack and the `addressof' expression is replaced with a `plus'
|
|||
|
expression for the address of its stack slot.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Arithmetic, Next: Comparisons, Prev: Regs and Memory, Up: RTL
|
|||
|
|
|||
|
RTL Expressions for Arithmetic
|
|||
|
==============================
|
|||
|
|
|||
|
Unless otherwise specified, all the operands of arithmetic
|
|||
|
expressions must be valid for mode M. An operand is valid for mode M
|
|||
|
if it has mode M, or if it is a `const_int' or `const_double' and M is
|
|||
|
a mode of class `MODE_INT'.
|
|||
|
|
|||
|
For commutative binary operations, constants should be placed in the
|
|||
|
second operand.
|
|||
|
|
|||
|
`(plus:M X Y)'
|
|||
|
Represents the sum of the values represented by X and Y carried
|
|||
|
out in machine mode M.
|
|||
|
|
|||
|
`(lo_sum:M X Y)'
|
|||
|
Like `plus', except that it represents that sum of X and the
|
|||
|
low-order bits of Y. The number of low order bits is
|
|||
|
machine-dependent but is normally the number of bits in a `Pmode'
|
|||
|
item minus the number of bits set by the `high' code (*note
|
|||
|
Constants::.).
|
|||
|
|
|||
|
M should be `Pmode'.
|
|||
|
|
|||
|
`(minus:M X Y)'
|
|||
|
Like `plus' but represents subtraction.
|
|||
|
|
|||
|
`(compare:M X Y)'
|
|||
|
Represents the result of subtracting Y from X for purposes of
|
|||
|
comparison. The result is computed without overflow, as if with
|
|||
|
infinite precision.
|
|||
|
|
|||
|
Of course, machines can't really subtract with infinite precision.
|
|||
|
However, they can pretend to do so when only the sign of the
|
|||
|
result will be used, which is the case when the result is stored
|
|||
|
in the condition code. And that is the only way this kind of
|
|||
|
expression may validly be used: as a value to be stored in the
|
|||
|
condition codes.
|
|||
|
|
|||
|
The mode M is not related to the modes of X and Y, but instead is
|
|||
|
the mode of the condition code value. If `(cc0)' is used, it is
|
|||
|
`VOIDmode'. Otherwise it is some mode in class `MODE_CC', often
|
|||
|
`CCmode'. *Note Condition Code::.
|
|||
|
|
|||
|
Normally, X and Y must have the same mode. Otherwise, `compare'
|
|||
|
is valid only if the mode of X is in class `MODE_INT' and Y is a
|
|||
|
`const_int' or `const_double' with mode `VOIDmode'. The mode of X
|
|||
|
determines what mode the comparison is to be done in; thus it must
|
|||
|
not be `VOIDmode'.
|
|||
|
|
|||
|
If one of the operands is a constant, it should be placed in the
|
|||
|
second operand and the comparison code adjusted as appropriate.
|
|||
|
|
|||
|
A `compare' specifying two `VOIDmode' constants is not valid since
|
|||
|
there is no way to know in what mode the comparison is to be
|
|||
|
performed; the comparison must either be folded during the
|
|||
|
compilation or the first operand must be loaded into a register
|
|||
|
while its mode is still known.
|
|||
|
|
|||
|
`(neg:M X)'
|
|||
|
Represents the negation (subtraction from zero) of the value
|
|||
|
represented by X, carried out in mode M.
|
|||
|
|
|||
|
`(mult:M X Y)'
|
|||
|
Represents the signed product of the values represented by X and Y
|
|||
|
carried out in machine mode M.
|
|||
|
|
|||
|
Some machines support a multiplication that generates a product
|
|||
|
wider than the operands. Write the pattern for this as
|
|||
|
|
|||
|
(mult:M (sign_extend:M X) (sign_extend:M Y))
|
|||
|
|
|||
|
where M is wider than the modes of X and Y, which need not be the
|
|||
|
same.
|
|||
|
|
|||
|
Write patterns for unsigned widening multiplication similarly using
|
|||
|
`zero_extend'.
|
|||
|
|
|||
|
`(div:M X Y)'
|
|||
|
Represents the quotient in signed division of X by Y, carried out
|
|||
|
in machine mode M. If M is a floating point mode, it represents
|
|||
|
the exact quotient; otherwise, the integerized quotient.
|
|||
|
|
|||
|
Some machines have division instructions in which the operands and
|
|||
|
quotient widths are not all the same; you should represent such
|
|||
|
instructions using `truncate' and `sign_extend' as in,
|
|||
|
|
|||
|
(truncate:M1 (div:M2 X (sign_extend:M2 Y)))
|
|||
|
|
|||
|
`(udiv:M X Y)'
|
|||
|
Like `div' but represents unsigned division.
|
|||
|
|
|||
|
`(mod:M X Y)'
|
|||
|
`(umod:M X Y)'
|
|||
|
Like `div' and `udiv' but represent the remainder instead of the
|
|||
|
quotient.
|
|||
|
|
|||
|
`(smin:M X Y)'
|
|||
|
`(smax:M X Y)'
|
|||
|
Represents the smaller (for `smin') or larger (for `smax') of X
|
|||
|
and Y, interpreted as signed integers in mode M.
|
|||
|
|
|||
|
`(umin:M X Y)'
|
|||
|
`(umax:M X Y)'
|
|||
|
Like `smin' and `smax', but the values are interpreted as unsigned
|
|||
|
integers.
|
|||
|
|
|||
|
`(not:M X)'
|
|||
|
Represents the bitwise complement of the value represented by X,
|
|||
|
carried out in mode M, which must be a fixed-point machine mode.
|
|||
|
|
|||
|
`(and:M X Y)'
|
|||
|
Represents the bitwise logical-and of the values represented by X
|
|||
|
and Y, carried out in machine mode M, which must be a fixed-point
|
|||
|
machine mode.
|
|||
|
|
|||
|
`(ior:M X Y)'
|
|||
|
Represents the bitwise inclusive-or of the values represented by X
|
|||
|
and Y, carried out in machine mode M, which must be a fixed-point
|
|||
|
mode.
|
|||
|
|
|||
|
`(xor:M X Y)'
|
|||
|
Represents the bitwise exclusive-or of the values represented by X
|
|||
|
and Y, carried out in machine mode M, which must be a fixed-point
|
|||
|
mode.
|
|||
|
|
|||
|
`(ashift:M X C)'
|
|||
|
Represents the result of arithmetically shifting X left by C
|
|||
|
places. X have mode M, a fixed-point machine mode. C be a
|
|||
|
fixed-point mode or be a constant with mode `VOIDmode'; which mode
|
|||
|
is determined by the mode called for in the machine description
|
|||
|
entry for the left-shift instruction. For example, on the Vax,
|
|||
|
the mode of C is `QImode' regardless of M.
|
|||
|
|
|||
|
`(lshiftrt:M X C)'
|
|||
|
`(ashiftrt:M X C)'
|
|||
|
Like `ashift' but for right shift. Unlike the case for left shift,
|
|||
|
these two operations are distinct.
|
|||
|
|
|||
|
`(rotate:M X C)'
|
|||
|
`(rotatert:M X C)'
|
|||
|
Similar but represent left and right rotate. If C is a constant,
|
|||
|
use `rotate'.
|
|||
|
|
|||
|
`(abs:M X)'
|
|||
|
Represents the absolute value of X, computed in mode M.
|
|||
|
|
|||
|
`(sqrt:M X)'
|
|||
|
Represents the square root of X, computed in mode M. Most often M
|
|||
|
will be a floating point mode.
|
|||
|
|
|||
|
`(ffs:M X)'
|
|||
|
Represents one plus the index of the least significant 1-bit in X,
|
|||
|
represented as an integer of mode M. (The value is zero if X is
|
|||
|
zero.) The mode of X need not be M; depending on the target
|
|||
|
machine, various mode combinations may be valid.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Comparisons, Next: Bit Fields, Prev: Arithmetic, Up: RTL
|
|||
|
|
|||
|
Comparison Operations
|
|||
|
=====================
|
|||
|
|
|||
|
Comparison operators test a relation on two operands and are
|
|||
|
considered to represent a machine-dependent nonzero value described by,
|
|||
|
but not necessarily equal to, `STORE_FLAG_VALUE' (*note Misc::.) if the
|
|||
|
relation holds, or zero if it does not. The mode of the comparison
|
|||
|
operation is independent of the mode of the data being compared. If
|
|||
|
the comparison operation is being tested (e.g., the first operand of an
|
|||
|
`if_then_else'), the mode must be `VOIDmode'. If the comparison
|
|||
|
operation is producing data to be stored in some variable, the mode
|
|||
|
must be in class `MODE_INT'. All comparison operations producing data
|
|||
|
must use the same mode, which is machine-specific.
|
|||
|
|
|||
|
There are two ways that comparison operations may be used. The
|
|||
|
comparison operators may be used to compare the condition codes `(cc0)'
|
|||
|
against zero, as in `(eq (cc0) (const_int 0))'. Such a construct
|
|||
|
actually refers to the result of the preceding instruction in which the
|
|||
|
condition codes were set. The instructing setting the condition code
|
|||
|
must be adjacent to the instruction using the condition code; only
|
|||
|
`note' insns may separate them.
|
|||
|
|
|||
|
Alternatively, a comparison operation may directly compare two data
|
|||
|
objects. The mode of the comparison is determined by the operands; they
|
|||
|
must both be valid for a common machine mode. A comparison with both
|
|||
|
operands constant would be invalid as the machine mode could not be
|
|||
|
deduced from it, but such a comparison should never exist in RTL due to
|
|||
|
constant folding.
|
|||
|
|
|||
|
In the example above, if `(cc0)' were last set to `(compare X Y)',
|
|||
|
the comparison operation is identical to `(eq X Y)'. Usually only one
|
|||
|
style of comparisons is supported on a particular machine, but the
|
|||
|
combine pass will try to merge the operations to produce the `eq' shown
|
|||
|
in case it exists in the context of the particular insn involved.
|
|||
|
|
|||
|
Inequality comparisons come in two flavors, signed and unsigned.
|
|||
|
Thus, there are distinct expression codes `gt' and `gtu' for signed and
|
|||
|
unsigned greater-than. These can produce different results for the same
|
|||
|
pair of integer values: for example, 1 is signed greater-than -1 but not
|
|||
|
unsigned greater-than, because -1 when regarded as unsigned is actually
|
|||
|
`0xffffffff' which is greater than 1.
|
|||
|
|
|||
|
The signed comparisons are also used for floating point values.
|
|||
|
Floating point comparisons are distinguished by the machine modes of
|
|||
|
the operands.
|
|||
|
|
|||
|
`(eq:M X Y)'
|
|||
|
1 if the values represented by X and Y are equal, otherwise 0.
|
|||
|
|
|||
|
`(ne:M X Y)'
|
|||
|
1 if the values represented by X and Y are not equal, otherwise 0.
|
|||
|
|
|||
|
`(gt:M X Y)'
|
|||
|
1 if the X is greater than Y. If they are fixed-point, the
|
|||
|
comparison is done in a signed sense.
|
|||
|
|
|||
|
`(gtu:M X Y)'
|
|||
|
Like `gt' but does unsigned comparison, on fixed-point numbers
|
|||
|
only.
|
|||
|
|
|||
|
`(lt:M X Y)'
|
|||
|
`(ltu:M X Y)'
|
|||
|
Like `gt' and `gtu' but test for "less than".
|
|||
|
|
|||
|
`(ge:M X Y)'
|
|||
|
`(geu:M X Y)'
|
|||
|
Like `gt' and `gtu' but test for "greater than or equal".
|
|||
|
|
|||
|
`(le:M X Y)'
|
|||
|
`(leu:M X Y)'
|
|||
|
Like `gt' and `gtu' but test for "less than or equal".
|
|||
|
|
|||
|
`(if_then_else COND THEN ELSE)'
|
|||
|
This is not a comparison operation but is listed here because it is
|
|||
|
always used in conjunction with a comparison operation. To be
|
|||
|
precise, COND is a comparison expression. This expression
|
|||
|
represents a choice, according to COND, between the value
|
|||
|
represented by THEN and the one represented by ELSE.
|
|||
|
|
|||
|
On most machines, `if_then_else' expressions are valid only to
|
|||
|
express conditional jumps.
|
|||
|
|
|||
|
`(cond [TEST1 VALUE1 TEST2 VALUE2 ...] DEFAULT)'
|
|||
|
Similar to `if_then_else', but more general. Each of TEST1,
|
|||
|
TEST2, ... is performed in turn. The result of this expression is
|
|||
|
the VALUE corresponding to the first non-zero test, or DEFAULT if
|
|||
|
none of the tests are non-zero expressions.
|
|||
|
|
|||
|
This is currently not valid for instruction patterns and is
|
|||
|
supported only for insn attributes. *Note Insn Attributes::.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Bit Fields, Next: Conversions, Prev: Comparisons, Up: RTL
|
|||
|
|
|||
|
Bit Fields
|
|||
|
==========
|
|||
|
|
|||
|
Special expression codes exist to represent bitfield instructions.
|
|||
|
These types of expressions are lvalues in RTL; they may appear on the
|
|||
|
left side of an assignment, indicating insertion of a value into the
|
|||
|
specified bit field.
|
|||
|
|
|||
|
`(sign_extract:M LOC SIZE POS)'
|
|||
|
This represents a reference to a sign-extended bit field contained
|
|||
|
or starting in LOC (a memory or register reference). The bit field
|
|||
|
is SIZE bits wide and starts at bit POS. The compilation option
|
|||
|
`BITS_BIG_ENDIAN' says which end of the memory unit POS counts
|
|||
|
from.
|
|||
|
|
|||
|
If LOC is in memory, its mode must be a single-byte integer mode.
|
|||
|
If LOC is in a register, the mode to use is specified by the
|
|||
|
operand of the `insv' or `extv' pattern (*note Standard Names::.)
|
|||
|
and is usually a full-word integer mode, which is the default if
|
|||
|
none is specified.
|
|||
|
|
|||
|
The mode of POS is machine-specific and is also specified in the
|
|||
|
`insv' or `extv' pattern.
|
|||
|
|
|||
|
The mode M is the same as the mode that would be used for LOC if
|
|||
|
it were a register.
|
|||
|
|
|||
|
`(zero_extract:M LOC SIZE POS)'
|
|||
|
Like `sign_extract' but refers to an unsigned or zero-extended bit
|
|||
|
field. The same sequence of bits are extracted, but they are
|
|||
|
filled to an entire word with zeros instead of by sign-extension.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Conversions, Next: RTL Declarations, Prev: Bit Fields, Up: RTL
|
|||
|
|
|||
|
Conversions
|
|||
|
===========
|
|||
|
|
|||
|
All conversions between machine modes must be represented by
|
|||
|
explicit conversion operations. For example, an expression which is
|
|||
|
the sum of a byte and a full word cannot be written as `(plus:SI
|
|||
|
(reg:QI 34) (reg:SI 80))' because the `plus' operation requires two
|
|||
|
operands of the same machine mode. Therefore, the byte-sized operand
|
|||
|
is enclosed in a conversion operation, as in
|
|||
|
|
|||
|
(plus:SI (sign_extend:SI (reg:QI 34)) (reg:SI 80))
|
|||
|
|
|||
|
The conversion operation is not a mere placeholder, because there
|
|||
|
may be more than one way of converting from a given starting mode to
|
|||
|
the desired final mode. The conversion operation code says how to do
|
|||
|
it.
|
|||
|
|
|||
|
For all conversion operations, X must not be `VOIDmode' because the
|
|||
|
mode in which to do the conversion would not be known. The conversion
|
|||
|
must either be done at compile-time or X must be placed into a register.
|
|||
|
|
|||
|
`(sign_extend:M X)'
|
|||
|
Represents the result of sign-extending the value X to machine
|
|||
|
mode M. M must be a fixed-point mode and X a fixed-point value of
|
|||
|
a mode narrower than M.
|
|||
|
|
|||
|
`(zero_extend:M X)'
|
|||
|
Represents the result of zero-extending the value X to machine
|
|||
|
mode M. M must be a fixed-point mode and X a fixed-point value of
|
|||
|
a mode narrower than M.
|
|||
|
|
|||
|
`(float_extend:M X)'
|
|||
|
Represents the result of extending the value X to machine mode M.
|
|||
|
M must be a floating point mode and X a floating point value of a
|
|||
|
mode narrower than M.
|
|||
|
|
|||
|
`(truncate:M X)'
|
|||
|
Represents the result of truncating the value X to machine mode M.
|
|||
|
M must be a fixed-point mode and X a fixed-point value of a mode
|
|||
|
wider than M.
|
|||
|
|
|||
|
`(float_truncate:M X)'
|
|||
|
Represents the result of truncating the value X to machine mode M.
|
|||
|
M must be a floating point mode and X a floating point value of a
|
|||
|
mode wider than M.
|
|||
|
|
|||
|
`(float:M X)'
|
|||
|
Represents the result of converting fixed point value X, regarded
|
|||
|
as signed, to floating point mode M.
|
|||
|
|
|||
|
`(unsigned_float:M X)'
|
|||
|
Represents the result of converting fixed point value X, regarded
|
|||
|
as unsigned, to floating point mode M.
|
|||
|
|
|||
|
`(fix:M X)'
|
|||
|
When M is a fixed point mode, represents the result of converting
|
|||
|
floating point value X to mode M, regarded as signed. How
|
|||
|
rounding is done is not specified, so this operation may be used
|
|||
|
validly in compiling C code only for integer-valued operands.
|
|||
|
|
|||
|
`(unsigned_fix:M X)'
|
|||
|
Represents the result of converting floating point value X to
|
|||
|
fixed point mode M, regarded as unsigned. How rounding is done is
|
|||
|
not specified.
|
|||
|
|
|||
|
`(fix:M X)'
|
|||
|
When M is a floating point mode, represents the result of
|
|||
|
converting floating point value X (valid for mode M) to an
|
|||
|
integer, still represented in floating point mode M, by rounding
|
|||
|
towards zero.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: RTL Declarations, Next: Side Effects, Prev: Conversions, Up: RTL
|
|||
|
|
|||
|
Declarations
|
|||
|
============
|
|||
|
|
|||
|
Declaration expression codes do not represent arithmetic operations
|
|||
|
but rather state assertions about their operands.
|
|||
|
|
|||
|
`(strict_low_part (subreg:M (reg:N R) 0))'
|
|||
|
This expression code is used in only one context: as the
|
|||
|
destination operand of a `set' expression. In addition, the
|
|||
|
operand of this expression must be a non-paradoxical `subreg'
|
|||
|
expression.
|
|||
|
|
|||
|
The presence of `strict_low_part' says that the part of the
|
|||
|
register which is meaningful in mode N, but is not part of mode M,
|
|||
|
is not to be altered. Normally, an assignment to such a subreg is
|
|||
|
allowed to have undefined effects on the rest of the register when
|
|||
|
M is less than a word.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Side Effects, Next: Incdec, Prev: RTL Declarations, Up: RTL
|
|||
|
|
|||
|
Side Effect Expressions
|
|||
|
=======================
|
|||
|
|
|||
|
The expression codes described so far represent values, not actions.
|
|||
|
But machine instructions never produce values; they are meaningful only
|
|||
|
for their side effects on the state of the machine. Special expression
|
|||
|
codes are used to represent side effects.
|
|||
|
|
|||
|
The body of an instruction is always one of these side effect codes;
|
|||
|
the codes described above, which represent values, appear only as the
|
|||
|
operands of these.
|
|||
|
|
|||
|
`(set LVAL X)'
|
|||
|
Represents the action of storing the value of X into the place
|
|||
|
represented by LVAL. LVAL must be an expression representing a
|
|||
|
place that can be stored in: `reg' (or `subreg' or
|
|||
|
`strict_low_part'), `mem', `pc' or `cc0'.
|
|||
|
|
|||
|
If LVAL is a `reg', `subreg' or `mem', it has a machine mode; then
|
|||
|
X must be valid for that mode.
|
|||
|
|
|||
|
If LVAL is a `reg' whose machine mode is less than the full width
|
|||
|
of the register, then it means that the part of the register
|
|||
|
specified by the machine mode is given the specified value and the
|
|||
|
rest of the register receives an undefined value. Likewise, if
|
|||
|
LVAL is a `subreg' whose machine mode is narrower than the mode of
|
|||
|
the register, the rest of the register can be changed in an
|
|||
|
undefined way.
|
|||
|
|
|||
|
If LVAL is a `strict_low_part' of a `subreg', then the part of the
|
|||
|
register specified by the machine mode of the `subreg' is given
|
|||
|
the value X and the rest of the register is not changed.
|
|||
|
|
|||
|
If LVAL is `(cc0)', it has no machine mode, and X may be either a
|
|||
|
`compare' expression or a value that may have any mode. The
|
|||
|
latter case represents a "test" instruction. The expression `(set
|
|||
|
(cc0) (reg:M N))' is equivalent to `(set (cc0) (compare (reg:M N)
|
|||
|
(const_int 0)))'. Use the former expression to save space during
|
|||
|
the compilation.
|
|||
|
|
|||
|
If LVAL is `(pc)', we have a jump instruction, and the
|
|||
|
possibilities for X are very limited. It may be a `label_ref'
|
|||
|
expression (unconditional jump). It may be an `if_then_else'
|
|||
|
(conditional jump), in which case either the second or the third
|
|||
|
operand must be `(pc)' (for the case which does not jump) and the
|
|||
|
other of the two must be a `label_ref' (for the case which does
|
|||
|
jump). X may also be a `mem' or `(plus:SI (pc) Y)', where Y may
|
|||
|
be a `reg' or a `mem'; these unusual patterns are used to
|
|||
|
represent jumps through branch tables.
|
|||
|
|
|||
|
If LVAL is neither `(cc0)' nor `(pc)', the mode of LVAL must not
|
|||
|
be `VOIDmode' and the mode of X must be valid for the mode of LVAL.
|
|||
|
|
|||
|
LVAL is customarily accessed with the `SET_DEST' macro and X with
|
|||
|
the `SET_SRC' macro.
|
|||
|
|
|||
|
`(return)'
|
|||
|
As the sole expression in a pattern, represents a return from the
|
|||
|
current function, on machines where this can be done with one
|
|||
|
instruction, such as Vaxes. On machines where a multi-instruction
|
|||
|
"epilogue" must be executed in order to return from the function,
|
|||
|
returning is done by jumping to a label which precedes the
|
|||
|
epilogue, and the `return' expression code is never used.
|
|||
|
|
|||
|
Inside an `if_then_else' expression, represents the value to be
|
|||
|
placed in `pc' to return to the caller.
|
|||
|
|
|||
|
Note that an insn pattern of `(return)' is logically equivalent to
|
|||
|
`(set (pc) (return))', but the latter form is never used.
|
|||
|
|
|||
|
`(call FUNCTION NARGS)'
|
|||
|
Represents a function call. FUNCTION is a `mem' expression whose
|
|||
|
address is the address of the function to be called. NARGS is an
|
|||
|
expression which can be used for two purposes: on some machines it
|
|||
|
represents the number of bytes of stack argument; on others, it
|
|||
|
represents the number of argument registers.
|
|||
|
|
|||
|
Each machine has a standard machine mode which FUNCTION must have.
|
|||
|
The machine description defines macro `FUNCTION_MODE' to expand
|
|||
|
into the requisite mode name. The purpose of this mode is to
|
|||
|
specify what kind of addressing is allowed, on machines where the
|
|||
|
allowed kinds of addressing depend on the machine mode being
|
|||
|
addressed.
|
|||
|
|
|||
|
`(clobber X)'
|
|||
|
Represents the storing or possible storing of an unpredictable,
|
|||
|
undescribed value into X, which must be a `reg', `scratch' or
|
|||
|
`mem' expression.
|
|||
|
|
|||
|
One place this is used is in string instructions that store
|
|||
|
standard values into particular hard registers. It may not be
|
|||
|
worth the trouble to describe the values that are stored, but it
|
|||
|
is essential to inform the compiler that the registers will be
|
|||
|
altered, lest it attempt to keep data in them across the string
|
|||
|
instruction.
|
|||
|
|
|||
|
If X is `(mem:BLK (const_int 0))', it means that all memory
|
|||
|
locations must be presumed clobbered.
|
|||
|
|
|||
|
Note that the machine description classifies certain hard
|
|||
|
registers as "call-clobbered". All function call instructions are
|
|||
|
assumed by default to clobber these registers, so there is no need
|
|||
|
to use `clobber' expressions to indicate this fact. Also, each
|
|||
|
function call is assumed to have the potential to alter any memory
|
|||
|
location, unless the function is declared `const'.
|
|||
|
|
|||
|
If the last group of expressions in a `parallel' are each a
|
|||
|
`clobber' expression whose arguments are `reg' or `match_scratch'
|
|||
|
(*note RTL Template::.) expressions, the combiner phase can add
|
|||
|
the appropriate `clobber' expressions to an insn it has
|
|||
|
constructed when doing so will cause a pattern to be matched.
|
|||
|
|
|||
|
This feature can be used, for example, on a machine that whose
|
|||
|
multiply and add instructions don't use an MQ register but which
|
|||
|
has an add-accumulate instruction that does clobber the MQ
|
|||
|
register. Similarly, a combined instruction might require a
|
|||
|
temporary register while the constituent instructions might not.
|
|||
|
|
|||
|
When a `clobber' expression for a register appears inside a
|
|||
|
`parallel' with other side effects, the register allocator
|
|||
|
guarantees that the register is unoccupied both before and after
|
|||
|
that insn. However, the reload phase may allocate a register used
|
|||
|
for one of the inputs unless the `&' constraint is specified for
|
|||
|
the selected alternative (*note Modifiers::.). You can clobber
|
|||
|
either a specific hard register, a pseudo register, or a `scratch'
|
|||
|
expression; in the latter two cases, GNU CC will allocate a hard
|
|||
|
register that is available there for use as a temporary.
|
|||
|
|
|||
|
For instructions that require a temporary register, you should use
|
|||
|
`scratch' instead of a pseudo-register because this will allow the
|
|||
|
combiner phase to add the `clobber' when required. You do this by
|
|||
|
coding (`clobber' (`match_scratch' ...)). If you do clobber a
|
|||
|
pseudo register, use one which appears nowhere else--generate a
|
|||
|
new one each time. Otherwise, you may confuse CSE.
|
|||
|
|
|||
|
There is one other known use for clobbering a pseudo register in a
|
|||
|
`parallel': when one of the input operands of the insn is also
|
|||
|
clobbered by the insn. In this case, using the same pseudo
|
|||
|
register in the clobber and elsewhere in the insn produces the
|
|||
|
expected results.
|
|||
|
|
|||
|
`(use X)'
|
|||
|
Represents the use of the value of X. It indicates that the value
|
|||
|
in X at this point in the program is needed, even though it may
|
|||
|
not be apparent why this is so. Therefore, the compiler will not
|
|||
|
attempt to delete previous instructions whose only effect is to
|
|||
|
store a value in X. X must be a `reg' expression.
|
|||
|
|
|||
|
During the delayed branch scheduling phase, X may be an insn.
|
|||
|
This indicates that X previously was located at this place in the
|
|||
|
code and its data dependencies need to be taken into account.
|
|||
|
These `use' insns will be deleted before the delayed branch
|
|||
|
scheduling phase exits.
|
|||
|
|
|||
|
`(parallel [X0 X1 ...])'
|
|||
|
Represents several side effects performed in parallel. The square
|
|||
|
brackets stand for a vector; the operand of `parallel' is a vector
|
|||
|
of expressions. X0, X1 and so on are individual side effect
|
|||
|
expressions--expressions of code `set', `call', `return',
|
|||
|
`clobber' or `use'.
|
|||
|
|
|||
|
"In parallel" means that first all the values used in the
|
|||
|
individual side-effects are computed, and second all the actual
|
|||
|
side-effects are performed. For example,
|
|||
|
|
|||
|
(parallel [(set (reg:SI 1) (mem:SI (reg:SI 1)))
|
|||
|
(set (mem:SI (reg:SI 1)) (reg:SI 1))])
|
|||
|
|
|||
|
says unambiguously that the values of hard register 1 and the
|
|||
|
memory location addressed by it are interchanged. In both places
|
|||
|
where `(reg:SI 1)' appears as a memory address it refers to the
|
|||
|
value in register 1 *before* the execution of the insn.
|
|||
|
|
|||
|
It follows that it is *incorrect* to use `parallel' and expect the
|
|||
|
result of one `set' to be available for the next one. For
|
|||
|
example, people sometimes attempt to represent a jump-if-zero
|
|||
|
instruction this way:
|
|||
|
|
|||
|
(parallel [(set (cc0) (reg:SI 34))
|
|||
|
(set (pc) (if_then_else
|
|||
|
(eq (cc0) (const_int 0))
|
|||
|
(label_ref ...)
|
|||
|
(pc)))])
|
|||
|
|
|||
|
But this is incorrect, because it says that the jump condition
|
|||
|
depends on the condition code value *before* this instruction, not
|
|||
|
on the new value that is set by this instruction.
|
|||
|
|
|||
|
Peephole optimization, which takes place together with final
|
|||
|
assembly code output, can produce insns whose patterns consist of
|
|||
|
a `parallel' whose elements are the operands needed to output the
|
|||
|
resulting assembler code--often `reg', `mem' or constant
|
|||
|
expressions. This would not be well-formed RTL at any other stage
|
|||
|
in compilation, but it is ok then because no further optimization
|
|||
|
remains to be done. However, the definition of the macro
|
|||
|
`NOTICE_UPDATE_CC', if any, must deal with such insns if you
|
|||
|
define any peephole optimizations.
|
|||
|
|
|||
|
`(sequence [INSNS ...])'
|
|||
|
Represents a sequence of insns. Each of the INSNS that appears in
|
|||
|
the vector is suitable for appearing in the chain of insns, so it
|
|||
|
must be an `insn', `jump_insn', `call_insn', `code_label',
|
|||
|
`barrier' or `note'.
|
|||
|
|
|||
|
A `sequence' RTX is never placed in an actual insn during RTL
|
|||
|
generation. It represents the sequence of insns that result from a
|
|||
|
`define_expand' *before* those insns are passed to `emit_insn' to
|
|||
|
insert them in the chain of insns. When actually inserted, the
|
|||
|
individual sub-insns are separated out and the `sequence' is
|
|||
|
forgotten.
|
|||
|
|
|||
|
After delay-slot scheduling is completed, an insn and all the
|
|||
|
insns that reside in its delay slots are grouped together into a
|
|||
|
`sequence'. The insn requiring the delay slot is the first insn
|
|||
|
in the vector; subsequent insns are to be placed in the delay slot.
|
|||
|
|
|||
|
`INSN_ANNULLED_BRANCH_P' is set on an insn in a delay slot to
|
|||
|
indicate that a branch insn should be used that will conditionally
|
|||
|
annul the effect of the insns in the delay slots. In such a case,
|
|||
|
`INSN_FROM_TARGET_P' indicates that the insn is from the target of
|
|||
|
the branch and should be executed only if the branch is taken;
|
|||
|
otherwise the insn should be executed only if the branch is not
|
|||
|
taken. *Note Delay Slots::.
|
|||
|
|
|||
|
These expression codes appear in place of a side effect, as the body
|
|||
|
of an insn, though strictly speaking they do not always describe side
|
|||
|
effects as such:
|
|||
|
|
|||
|
`(asm_input S)'
|
|||
|
Represents literal assembler code as described by the string S.
|
|||
|
|
|||
|
`(unspec [OPERANDS ...] INDEX)'
|
|||
|
`(unspec_volatile [OPERANDS ...] INDEX)'
|
|||
|
Represents a machine-specific operation on OPERANDS. INDEX
|
|||
|
selects between multiple machine-specific operations.
|
|||
|
`unspec_volatile' is used for volatile operations and operations
|
|||
|
that may trap; `unspec' is used for other operations.
|
|||
|
|
|||
|
These codes may appear inside a `pattern' of an insn, inside a
|
|||
|
`parallel', or inside an expression.
|
|||
|
|
|||
|
`(addr_vec:M [LR0 LR1 ...])'
|
|||
|
Represents a table of jump addresses. The vector elements LR0,
|
|||
|
etc., are `label_ref' expressions. The mode M specifies how much
|
|||
|
space is given to each address; normally M would be `Pmode'.
|
|||
|
|
|||
|
`(addr_diff_vec:M BASE [LR0 LR1 ...])'
|
|||
|
Represents a table of jump addresses expressed as offsets from
|
|||
|
BASE. The vector elements LR0, etc., are `label_ref' expressions
|
|||
|
and so is BASE. The mode M specifies how much space is given to
|
|||
|
each address-difference.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Incdec, Next: Assembler, Prev: Side Effects, Up: RTL
|
|||
|
|
|||
|
Embedded Side-Effects on Addresses
|
|||
|
==================================
|
|||
|
|
|||
|
Four special side-effect expression codes appear as memory addresses.
|
|||
|
|
|||
|
`(pre_dec:M X)'
|
|||
|
Represents the side effect of decrementing X by a standard amount
|
|||
|
and represents also the value that X has after being decremented.
|
|||
|
X must be a `reg' or `mem', but most machines allow only a `reg'.
|
|||
|
M must be the machine mode for pointers on the machine in use.
|
|||
|
The amount X is decremented by is the length in bytes of the
|
|||
|
machine mode of the containing memory reference of which this
|
|||
|
expression serves as the address. Here is an example of its use:
|
|||
|
|
|||
|
(mem:DF (pre_dec:SI (reg:SI 39)))
|
|||
|
|
|||
|
This says to decrement pseudo register 39 by the length of a
|
|||
|
`DFmode' value and use the result to address a `DFmode' value.
|
|||
|
|
|||
|
`(pre_inc:M X)'
|
|||
|
Similar, but specifies incrementing X instead of decrementing it.
|
|||
|
|
|||
|
`(post_dec:M X)'
|
|||
|
Represents the same side effect as `pre_dec' but a different
|
|||
|
value. The value represented here is the value X has before being
|
|||
|
decremented.
|
|||
|
|
|||
|
`(post_inc:M X)'
|
|||
|
Similar, but specifies incrementing X instead of decrementing it.
|
|||
|
|
|||
|
These embedded side effect expressions must be used with care.
|
|||
|
Instruction patterns may not use them. Until the `flow' pass of the
|
|||
|
compiler, they may occur only to represent pushes onto the stack. The
|
|||
|
`flow' pass finds cases where registers are incremented or decremented
|
|||
|
in one instruction and used as an address shortly before or after;
|
|||
|
these cases are then transformed to use pre- or post-increment or
|
|||
|
-decrement.
|
|||
|
|
|||
|
If a register used as the operand of these expressions is used in
|
|||
|
another address in an insn, the original value of the register is used.
|
|||
|
Uses of the register outside of an address are not permitted within the
|
|||
|
same insn as a use in an embedded side effect expression because such
|
|||
|
insns behave differently on different machines and hence must be treated
|
|||
|
as ambiguous and disallowed.
|
|||
|
|
|||
|
An instruction that can be represented with an embedded side effect
|
|||
|
could also be represented using `parallel' containing an additional
|
|||
|
`set' to describe how the address register is altered. This is not
|
|||
|
done because machines that allow these operations at all typically
|
|||
|
allow them wherever a memory address is called for. Describing them as
|
|||
|
additional parallel stores would require doubling the number of entries
|
|||
|
in the machine description.
|
|||
|
|
|||
|
|
|||
|
File: gcc.info, Node: Assembler, Next: Insns, Prev: Incdec, Up: RTL
|
|||
|
|
|||
|
Assembler Instructions as Expressions
|
|||
|
=====================================
|
|||
|
|
|||
|
The RTX code `asm_operands' represents a value produced by a
|
|||
|
user-specified assembler instruction. It is used to represent an `asm'
|
|||
|
statement with arguments. An `asm' statement with a single output
|
|||
|
operand, like this:
|
|||
|
|
|||
|
asm ("foo %1,%2,%0" : "=a" (outputvar) : "g" (x + y), "di" (*z));
|
|||
|
|
|||
|
is represented using a single `asm_operands' RTX which represents the
|
|||
|
value that is stored in `outputvar':
|
|||
|
|
|||
|
(set RTX-FOR-OUTPUTVAR
|
|||
|
(asm_operands "foo %1,%2,%0" "a" 0
|
|||
|
[RTX-FOR-ADDITION-RESULT RTX-FOR-*Z]
|
|||
|
[(asm_input:M1 "g")
|
|||
|
(asm_input:M2 "di")]))
|
|||
|
|
|||
|
Here the operands of the `asm_operands' RTX are the assembler template
|
|||
|
string, the output-operand's constraint, the index-number of the output
|
|||
|
operand among the output operands specified, a vector of input operand
|
|||
|
RTX's, and a vector of input-operand modes and constraints. The mode
|
|||
|
M1 is the mode of the sum `x+y'; M2 is that of `*z'.
|
|||
|
|
|||
|
When an `asm' statement has multiple output values, its insn has
|
|||
|
several such `set' RTX's inside of a `parallel'. Each `set' contains a
|
|||
|
`asm_operands'; all of these share the same assembler template and
|
|||
|
vectors, but each contains the constraint for the respective output
|
|||
|
operand. They are also distinguished by the output-operand index
|
|||
|
number, which is 0, 1, ... for successive output operands.
|
|||
|
|