📄 extend.texi
字号:
For example, here is how to use the 68881's @code{fsinx} instruction:@exampleasm ("fsinx %1,%0" : "=f" (result) : "f" (angle));@end example@noindent@ifset INTERNALSHere @code{angle} is the C expression for the input operand while@code{result} is that of the output operand. Each has @samp{"f"} as itsoperand constraint, saying that a floating point register is required. The@samp{=} in @samp{=f} indicates that the operand is an output; all outputoperands' constraints must use @samp{=}. The constraints use the samelanguage used in the machine description (@pxref{Constraints}).@end ifset@ifclear INTERNALSHere @code{angle} is the C expression for the input operand while@code{result} is that of the output operand. Each has @samp{"f"} as itsoperand constraint, saying that a floating point register is required. The@samp{=} in @samp{=f} indicates that the operand is an output; all outputoperands' constraints must use @samp{=}. The constraints use the samelanguage used in the machine description (@pxref{Constraints,,OperandConstraints, gcc.info, Using and Porting GCC}).@end ifclearEach operand is described by an operand-constraint string followed by the Cexpression in parentheses. A colon separates the assembler template fromthe first output operand, and another separates the last output operandfrom the first input, if any. Commas separate output operands and separateinputs. The total number of operands is limited to ten or to the maximumnumber of operands in any instruction pattern in the machine description,whichever is greater.If there are no output operands, and there are input operands, then theremust be two consecutive colons surrounding the place where the outputoperands would go.Output operand expressions must be lvalues; the compiler can check this.The input operands need not be lvalues. The compiler cannot check whetherthe operands have data types that are reasonable for the instruction beingexecuted. It does not parse the assembler instruction template and doesnot know what it means, or whether it is valid assembler input. Theextended @code{asm} feature is most often used for machine instructionsthat the compiler itself does not know exist.The output operands must be write-only; GNU CC will assume that the valuesin these operands before the instruction are dead and need not begenerated. Extended asm does not support input-output or read-writeoperands. For this reason, the constraint character @samp{+}, whichindicates such an operand, may not be used.When the assembler instruction has a read-write operand, or an operandin which only some of the bits are to be changed, you must logicallysplit its function into two separate operands, one input operand and onewrite-only output operand. The connection between them is expressed byconstraints which say they need to be in the same location when theinstruction executes. You can use the same C expression for bothoperands, or different expressions. For example, here we write the(fictitious) @samp{combine} instruction with @code{bar} as its read-onlysource operand and @code{foo} as its read-write destination:@exampleasm ("combine %2,%0" : "=r" (foo) : "0" (foo), "g" (bar));@end example@noindentThe constraint @samp{"0"} for operand 1 says that it must occupy the samelocation as operand 0. A digit in constraint is allowed only in an inputoperand, and it must refer to an output operand.Only a digit in the constraint can guarantee that one operand will be inthe same place as another. The mere fact that @code{foo} is the value ofboth operands is not enough to guarantee that they will be in the sameplace in the generated assembler code. The following would not work:@exampleasm ("combine %2,%0" : "=r" (foo) : "r" (foo), "g" (bar));@end exampleVarious optimizations or reloading could cause operands 0 and 1 to be indifferent registers; GNU CC knows no reason not to do so. For example, thecompiler might find a copy of the value of @code{foo} in one register anduse it for operand 1, but generate the output operand 0 in a differentregister (copying it afterward to @code{foo}'s own address). Of course,since the register for operand 1 is not even mentioned in the assemblercode, the result will not work, but GNU CC can't tell that.Some instructions clobber specific hard registers. To describe this, writea third colon after the input operands, followed by the names of theclobbered hard registers (given as strings). Here is a realistic examplefor the Vax:@exampleasm volatile ("movc3 %0,%1,%2" : /* no outputs */ : "g" (from), "g" (to), "g" (count) : "r0", "r1", "r2", "r3", "r4", "r5");@end exampleIf you refer to a particular hardware register from the assembler code,then you will probably have to list the register after the third colonto tell the compiler that the register's value is modified. In manyassemblers, the register names begin with @samp{%}; to produce one@samp{%} in the assembler code, you must write @samp{%%} in the input.If your assembler instruction can alter the condition code register,add @samp{cc} to the list of clobbered registers. GNU CC on somemachines represents the condition codes as a specific hardwareregister; @samp{cc} serves to name this register. On other machines,the condition code is handled differently, and specifying @samp{cc}has no effect. But it is valid no matter what the machine.If your assembler instruction modifies memory in an unpredicablefashion, add @samp{memory} to the list of clobbered registers.This will cause GNU CC to not keep memory values cached inregisters across the assembler instruction.You can put multiple assembler instructions together in a single @code{asm}template, separated either with newlines (written as @samp{\n}) or withsemicolons if the assembler allows such semicolons. The GNU assemblerallows semicolons and all Unix assemblers seem to do so. The inputoperands are guaranteed not to use any of the clobbered registers, andneither will the output operands' addresses, so you can read and write theclobbered registers as many times as you like. Here is an example ofmultiple instructions in a template; it assumes that the subroutine@code{_foo} accepts arguments in registers 9 and 10:@exampleasm ("movl %0,r9;movl %1,r10;call _foo" : /* no outputs */ : "g" (from), "g" (to) : "r9", "r10");@end example@ifset INTERNALSUnless an output operand has the @samp{&} constraint modifier, GNU CC mayallocate it in the same register as an unrelated input operand, on theassumption that the inputs are consumed before the outputs are produced.This assumption may be false if the assembler code actually consists ofmore than one instruction. In such a case, use @samp{&} for each outputoperand that may not overlap an input.@xref{Modifiers}.@end ifset@ifclear INTERNALSUnless an output operand has the @samp{&} constraint modifier, GNU CC mayallocate it in the same register as an unrelated input operand, on theassumption that the inputs are consumed before the outputs are produced.This assumption may be false if the assembler code actually consists ofmore than one instruction. In such a case, use @samp{&} for each outputoperand that may not overlap an input.@xref{Modifiers,,Constraint Modifier Characters,gcc.info,Using andPorting GCC}.@end ifclearIf you want to test the condition code produced by an assembler instruction,you must include a branch and a label in the @code{asm} construct, as follows:@exampleasm ("clr %0;frob %1;beq 0f;mov #1,%0;0:" : "g" (result) : "g" (input));@end example@noindentThis assumes your assembler supports local labels, as the GNU assemblerand most Unix assemblers do.@cindex macros containing @code{asm}Usually the most convenient way to use these @code{asm} instructions is toencapsulate them in macros that look like functions. For example,@example#define sin(x) \(@{ double __value, __arg = (x); \ asm ("fsinx %1,%0": "=f" (__value): "f" (__arg)); \ __value; @})@end example@noindentHere the variable @code{__arg} is used to make sure that the instructionoperates on a proper @code{double} value, and to accept only thosearguments @code{x} which can convert automatically to a @code{double}.Another way to make sure the instruction operates on the correct data typeis to use a cast in the @code{asm}. This is different from using avariable @code{__arg} in that it converts more different types. Forexample, if the desired type were @code{int}, casting the argument to@code{int} would accept a pointer with no complaint, while assigning theargument to an @code{int} variable named @code{__arg} would warn aboutusing a pointer unless the caller explicitly casts it.If an @code{asm} has output operands, GNU CC assumes for optimizationpurposes that the instruction has no side effects except to change theoutput operands. This does not mean that instructions with a side effectcannot be used, but you must be careful, because the compiler may eliminatethem if the output operands aren't used, or move them out of loops, orreplace two with one if they constitute a common subexpression. Also, ifyour instruction does have a side effect on a variable that otherwiseappears not to change, the old value of the variable may be reused later ifit happens to be found in a register.You can prevent an @code{asm} instruction from being deleted, movedsignificantly, or combined, by writing the keyword @code{volatile} afterthe @code{asm}. For example:@example#define set_priority(x) \asm volatile ("set_priority %0": /* no outputs */ : "g" (x))@end example@noindentAn instruction without output operands will not be deleted or movedsignificantly, regardless, unless it is unreachable.Note that even a volatile @code{asm} instruction can be moved in waysthat appear insignificant to the compiler, such as across jumpinstructions. You can't expect a sequence of volatile @code{asm}instructions to remain perfectly consecutive. If you want consecutiveoutput, use a single @code{asm}.It is a natural idea to look for a way to give access to the conditioncode left by the assembler instruction. However, when we attempted toimplement this, we found no way to make it work reliably. The problemis that output operands might need reloading, which would result inadditional following ``store'' instructions. On most machines, theseinstructions would alter the condition code before there was time totest it. This problem doesn't arise for ordinary ``test'' and``compare'' instructions because they don't have any output operands.If you are writing a header file that should be includable in ANSI Cprograms, write @code{__asm__} instead of @code{asm}. @xref{AlternateKeywords}.@node Asm Labels@section Controlling Names Used in Assembler Code@cindex assembler names for identifiers@cindex names used in assembler code@cindex identifiers, names in assembler codeYou can specify the name to be used in the assembler code for a Cfunction or variable by writing the @code{asm} (or @code{__asm__})keyword after the declarator as follows:@exampleint foo asm ("myfoo") = 2;@end example@noindentThis specifies that the name to be used for the variable @code{foo} inthe assembler code should be @samp{myfoo} rather than the usual@samp{_foo}.On systems where an underscore is normally prepended to the name of a Cfunction or variable, this feature allows you to define names for thelinker that do not start with an underscore.You cannot use @code{asm} in this way in a function @emph{definition}; butyou can get the same effect by writing a declaration for the functionbefore its definition and putting @code{asm} there, like this:@exampleextern func () asm ("FUNC");func (x, y) int x, y;@dots{}@end exampleIt is up to you to make sure that the assembler names you choose do notconflict with any other assembler symbols. Also, you must not use aregister name; that would produce completely invalid assembler code. GNUCC does not as yet have the ability to store static variables in registers.Perhaps that will be added.@node Explicit Reg Vars@section Variables in Specified Registers@cindex explicit register variables@cindex variables in specified registers@cindex specified registers@cindex registers, global allocationGNU C allows you to put a few global variables into specified hardwareregisters. You can also specify the register in which an ordinaryregister variable should be allocated.@itemize @bullet@itemGlobal register variables reserve registers throughout the program.This may be useful in programs such as programming languageinterpreters which have a couple of global variables that are accessedvery often.@itemLocal register variables in specific registers do not reserve theregisters. The compiler's data flow analysis is capable of determiningwhere the specified registers contain live values, and where they areavailable for other uses.These local variables are sometimes convenient for use with the extended@code{asm} feature (@pxref{Extended Asm}), if you want to write oneoutput of the assembler instruction directly into a particular register.(This will work provided the register you specify fits the constraintsspecified for that operand in the @code{asm}.)@end itemize@menu* Global Reg Vars::* Local Reg Vars::@end menu@node Global Reg Vars@subsection Defining Global Register Variables@cindex global register variables@cindex registers, global variables inYou can define a global register variable in GNU C like this:@exampleregister int *foo asm ("a5");@end example@noindentHere @code{a5} is the name of the register which should be used. Choose aregister which is normally saved and restored by function calls on yourmachine, so that library routines will not clobber it.Naturally the register name is cpu-dependent, so you would need toconditionalize your program according to cpu type. The register@code{a5} would be a good choice on a 68000 for a variable of pointertype. On machines with register windows, be sure to choose a ``global''register that is not affected magically by the function call mechanism.In addition, operating systems on one type of cpu may differ in how theyname the registers; then you would need additional conditionals. Forexample, some 68000 operating systems call this register @code{%a5}.Eventually there may be a way of asking the compiler to choose a registerautomatically, but first we need to figure out how it should choose andhow to enable you to guide the choice. No solution is evident.Defining a global register variable in a certain register reserves thatregister entirely for this use, at least within the current compilation.The register will not be allocated for any other purpose in the functionsin the current compilation. The register will not be saved and restored bythese functions. Stores into this register are never deleted even if theywould appear to be dead, but references may be deleted or moved orsimplified.It is not safe to access the global register variables from signalhandlers, or from more than one thread of control, because the systemlibrary routines may temporarily use the register for other things (unlessyou recompile them specially for the task at hand).@cindex @code{qsort}, and global register variablesIt is not safe for one function that uses a global register variable tocall another such function @code{foo} by way of a third function@code{lose} that was compiled without knowledge of this variable (i.e. in adifferent source file in which the variable wasn't declared). This isbecause @code{lose} might save the register and put some other value there.For example, you can't expect a global register variable to be available inthe comparison-function that you pass to @code{qsort}, since @code{qsort}might have put something else in that register. (If you are prepared torecompile @code{qsort} with the same global register variable, you cansolve this problem.)If you want to rec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -