If you use the same __asm operand for both input
and output, you must take care that you tell the compiler that the
input __asm operand refers to the same variable as
the corresponding output __asm operand. For example,
the code format string in Figure 1 uses
one register to store a single __asm operand that
is used for both input and output.
Definition of __asm operands for
both input and output via an operand list
This
topic describes how to use a code format string to define __asm operands
that can be used for both input and output.
You can use either
input and output operand strings both incorrectly (Figure 1) and correctly (Figure 3). The code in Figure 1 is incorrect because the
AR statement reads the first operand and then modifies it, but the =r constraint
specifies the output aspect only.
Figure 1. Incorrect __asm operand definition for both
input and output __asm ( " AR %0,%1" : "=r"(x) : "r"(y) ); 1
Note: No input operand is specified for variable x.
The compiler will not know that input and output are stored in the
same variable.
The compiler-generated HLASM source code
in
Figure 2 is the result of the
incorrect definition in
Figure 1.
Figure 2. Incorrect compiler-generated
HLASM source code from the incorrect __asm operand definition for
both input and output L 2,@4y 1
LA 1,@3x
AR 4,2
ST 4,0(,1)
Note: GPR 4, which is meant for input as well as output, is
not loaded from variable
x before the code format
string is embedded because the code format string in
Figure 1 specified variable
x as
an output operand only.
If a code format string uses
a single
__asm operand for both input and output,
you must ensure that the embedded assembly statements will perform
both of the following tasks:
- Define the variable as an input operand as well as an output operand.
- Define both an input operand and an output operand that refers
to the same variable. The variable name is not sufficient for this
purpose. See Figure 3.
Figure 3 shows
the code format string that will embed the correct assembler statements
(as shown in
Figure 4).
Figure 3. Successful definition of
an __asm operand for both input and output __asm ( " AR %0, %1" : "=r"(x) : "r"(y), "0"(x) );
1 2 3 4
Notes: - %0 is the first operand in the code format string.
- This example has one output __asm operand, "=r"(x).
- Within the input __asm operand list "r"(y),
"0"(x), the __asm operands are separated
by a comma.
- An input operand "0"(x) is added to the input
field. The constraint of this __asm operand is the ("0"),
which tells the compiler that:
- This input __asm operand is the same as the output __asm operand %0.
(A numeral zero in the constraint ("0") refers to %0;
a numeral one in a constraint would refer to %1;
and so on.)
- The register needs to be loaded with variable x,
as shown in Figure 4, before
the code format string is embedded in the HLASM output.
The compiler-generated HLASM source code in
Figure 4 is the result of the correct
definition in
Figure 3.
Figure 4. Correct compiler-generated
HLASM source code from the correct __asm operand definition for both
input and output L 2,@4y
L 4,@3x 1
LA 1,@3x
AR 4,2
ST 4,0(,1)
Note: The compiler inserted
L 4,@3x at the
beginning of the instruction sequence because the code format string
in
Figure 3 included both
the output operand
"=r"(x) and the input operand
"0"(x).
Together, these statements tell the compiler that the register for
the first operand
%0 will be used for variable
x,
which has a value that can be either an input or an output operand.
Definition of an __asm operand for
both input and output via the "+" constraint
You
can also use the "+" constraint to specify that an __asm operand
is used for both input and output.
In Figure 5, the "+" constraint
is used to define that the variable x is used both
as input and output.
Figure 5. The
+ constraint to define an __asm operand for both input and output __asm ( " AR %0, %1" : "+r"(x) : "r"(y));
Note: This example is parsed as though the operand list in
Figure 3 is given.
Note that an operand can be matched only once. When
you use the "+" constraint to implicitly define matching
input and output __asm operands, do not explicitly
define a corresponding __asm operand.
Figure 6 shows an erroneous example of
an __asm operand that is defined both implicitly
and explicitly. The notes identify the unnecessary code.
Figure 6. Error: Redundant definition of
an __asm operand __asm ( " AR %0, %1" : "+r"(x) : "r"(y), “0”(x));
1 2 3
Notes: - %0 is the first operand in the code format string.
- This example has one output __asm operand, "+r"(x).
The "+" constraint implicitly defines a matching input __asm operand.
- You do not have to define __asm operand "0"(x) explicitly.