⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extended-asm.html

📁 gcc手册
💻 HTML
📖 第 1 页 / 共 2 页
字号:
is an example of multiple instructions in a template; it assumes the

subroutine <code>_foo</code> accepts arguments in registers 9 and 10:



<pre class="example">     asm ("movl %0,r9\n\tmovl %1,r10\n\tcall _foo"

          : /* no outputs */

          : "g" (from), "g" (to)

          : "r9", "r10");

     </pre>



   <p>Unless an output operand has the <code>&amp;</code> constraint modifier, GCC

may allocate it in the same register as an unrelated input operand, on

the assumption the inputs are consumed before the outputs are produced. 

This assumption may be false if the assembler code actually consists of

more than one instruction.  In such a case, use <code>&amp;</code> for each output

operand that may not overlap an input.  See <a href="Modifiers.html#Modifiers">Modifiers</a>.



   <p>If you want to test the condition code produced by an assembler

instruction, you must include a branch and a label in the <code>asm</code>

construct, as follows:



<pre class="example">     asm ("clr %0\n\tfrob %1\n\tbeq 0f\n\tmov #1,%0\n0:"

          : "g" (result)

          : "g" (input));

     </pre>



<p>This assumes your assembler supports local labels, as the GNU assembler

and most Unix assemblers do.



   <p>Speaking of labels, jumps from one <code>asm</code> to another are not

supported.  The compiler's optimizers do not know about these jumps, and

therefore they cannot take account of them when deciding how to

optimize.



   <p>Usually the most convenient way to use these <code>asm</code> instructions is to

encapsulate them in macros that look like functions.  For example,



<pre class="example">     #define sin(x)       \

     ({ double __value, __arg = (x);   \

        asm ("fsinx %1,%0": "=f" (__value): "f" (__arg));  \

        __value; })

     </pre>



<p>Here the variable <code>__arg</code> is used to make sure that the instruction

operates on a proper <code>double</code> value, and to accept only those

arguments <code>x</code> which can convert automatically to a <code>double</code>.



   <p>Another way to make sure the instruction operates on the correct data

type is to use a cast in the <code>asm</code>.  This is different from using a

variable <code>__arg</code> in that it converts more different types.  For

example, if the desired type were <code>int</code>, casting the argument to

<code>int</code> would accept a pointer with no complaint, while assigning the

argument to an <code>int</code> variable named <code>__arg</code> would warn about

using a pointer unless the caller explicitly casts it.



   <p>If an <code>asm</code> has output operands, GCC assumes for optimization

purposes the instruction has no side effects except to change the output

operands.  This does not mean instructions with a side effect cannot be

used, but you must be careful, because the compiler may eliminate them

if the output operands aren't used, or move them out of loops, or

replace two with one if they constitute a common subexpression.  Also,

if your instruction does have a side effect on a variable that otherwise

appears not to change, the old value of the variable may be reused later

if it happens to be found in a register.



   <p>You can prevent an <code>asm</code> instruction from being deleted, moved

significantly, or combined, by writing the keyword <code>volatile</code> after

the <code>asm</code>.  For example:



<pre class="example">     #define get_and_set_priority(new)              \

     ({ int __old;                                  \

        asm volatile ("get_and_set_priority %0, %1" \

                      : "=g" (__old) : "g" (new));  \

        __old; })

     </pre>



<p>If you write an <code>asm</code> instruction with no outputs, GCC will know

the instruction has side-effects and will not delete the instruction or

move it outside of loops.



   <p>The <code>volatile</code> keyword indicates that the instruction has

important side-effects.  GCC will not delete a volatile <code>asm</code> if

it is reachable.  (The instruction can still be deleted if GCC can

prove that control-flow will never reach the location of the

instruction.)  In addition, GCC will not reschedule instructions

across a volatile <code>asm</code> instruction.  For example:



<pre class="example">     *(volatile int *)addr = foo;

     asm volatile ("eieio" : : );

     </pre>



<p>Assume <code>addr</code> contains the address of a memory mapped device

register.  The PowerPC <code>eieio</code> instruction (Enforce In-order

Execution of I/O) tells the CPU to make sure that the store to that

device register happens before it issues any other I/O.



   <p>Note that even a volatile <code>asm</code> instruction can be moved in ways

that appear insignificant to the compiler, such as across jump

instructions.  You can't expect a sequence of volatile <code>asm</code>

instructions to remain perfectly consecutive.  If you want consecutive

output, use a single <code>asm</code>.  Also, GCC will perform some

optimizations across a volatile <code>asm</code> instruction; GCC does not

"forget everything" when it encounters a volatile <code>asm</code>

instruction the way some other compilers do.



   <p>An <code>asm</code> instruction without any operands or clobbers (an "old

style" <code>asm</code>) will be treated identically to a volatile

<code>asm</code> instruction.



   <p>It is a natural idea to look for a way to give access to the condition

code left by the assembler instruction.  However, when we attempted to

implement this, we found no way to make it work reliably.  The problem

is that output operands might need reloading, which would result in

additional following "store" instructions.  On most machines, these

instructions would alter the condition code before there was time to

test it.  This problem doesn't arise for ordinary "test" and

"compare" instructions because they don't have any output operands.



   <p>For reasons similar to those described above, it is not possible to give

an assembler instruction access to the condition code left by previous

instructions.



   <p>If you are writing a header file that should be includable in ISO C

programs, write <code>__asm__</code> instead of <code>asm</code>.  See <a href="Alternate-Keywords.html#Alternate%20Keywords">Alternate Keywords</a>.



<h4 class="subsection">i386 floating point asm operands</h4>



   <p>There are several rules on the usage of stack-like regs in

asm_operands insns.  These rules apply only to the operands that are

stack-like regs:



     <ol type=1 start=1>

<li>Given a set of input regs that die in an asm_operands, it is

necessary to know which are implicitly popped by the asm, and

which must be explicitly popped by gcc.



     <p>An input reg that is implicitly popped by the asm must be

explicitly clobbered, unless it is constrained to match an

output operand.



     </p><li>For any input reg that is implicitly popped by an asm, it is

necessary to know how to adjust the stack to compensate for the pop. 

If any non-popped input is closer to the top of the reg-stack than

the implicitly popped reg, it would not be possible to know what the

stack looked like--it's not clear how the rest of the stack "slides

up".



     <p>All implicitly popped input regs must be closer to the top of

the reg-stack than any input that is not implicitly popped.



     <p>It is possible that if an input dies in an insn, reload might

use the input reg for an output reload.  Consider this example:



     <pre class="example">          asm ("foo" : "=t" (a) : "f" (b));

          </pre>



     <p>This asm says that input B is not popped by the asm, and that

the asm pushes a result onto the reg-stack, i.e., the stack is one

deeper after the asm than it was before.  But, it is possible that

reload will think that it can use the same reg for both the input and

the output, if input B dies in this insn.



     <p>If any input operand uses the <code>f</code> constraint, all output reg

constraints must use the <code>&amp;</code> earlyclobber.



     <p>The asm above would be written as



     <pre class="example">          asm ("foo" : "=&amp;t" (a) : "f" (b));

          </pre>



     </p><li>Some operands need to be in particular places on the stack.  All

output operands fall in this category--there is no other way to

know which regs the outputs appear in unless the user indicates

this in the constraints.



     <p>Output operands must specifically indicate which reg an output

appears in after an asm.  <code>=f</code> is not allowed: the operand

constraints must select a class with a single reg.



     </p><li>Output operands may not be "inserted" between existing stack regs. 

Since no 387 opcode uses a read/write operand, all output operands

are dead before the asm_operands, and are pushed by the asm_operands. 

It makes no sense to push anywhere but the top of the reg-stack.



     <p>Output operands must start at the top of the reg-stack: output

operands may not "skip" a reg.



     </p><li>Some asm statements may need extra stack space for internal

calculations.  This can be guaranteed by clobbering stack registers

unrelated to the inputs and outputs.



        </ol>



   <p>Here are a couple of reasonable asms to want to write.  This asm

takes one input, which is internally popped, and produces two outputs.



<pre class="example">     asm ("fsincos" : "=t" (cos), "=u" (sin) : "0" (inp));

     </pre>



   <p>This asm takes two inputs, which are popped by the <code>fyl2xp1</code> opcode,

and replaces them with one output.  The user must code the <code>st(1)</code>

clobber for reg-stack.c to know that <code>fyl2xp1</code> pops both inputs.



<pre class="example">     asm ("fyl2xp1" : "=t" (result) : "0" (x), "u" (y) : "st(1)");

     </pre>



   </body></html>



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -