2015-02-20 Arnaud Charlet <charlet@adacore.com>
[official-gcc.git] / gcc / ada / doc / gnat_ugn / inline_assembler.rst
blobd79b70b08147048a944047f8dc9123f3e8d2be33
1 .. _Inline_Assembler:
3 ****************
4 Inline Assembler
5 ****************
7 .. index:: Inline Assembler
9 If you need to write low-level software that interacts directly
10 with the hardware, Ada provides two ways to incorporate assembly
11 language code into your program.  First, you can import and invoke
12 external routines written in assembly language, an Ada feature fully
13 supported by GNAT.  However, for small sections of code it may be simpler
14 or more efficient to include assembly language statements directly
15 in your Ada source program, using the facilities of the implementation-defined
16 package `System.Machine_Code`, which incorporates the gcc
17 Inline Assembler.  The Inline Assembler approach offers a number of advantages,
18 including the following:
20 * No need to use non-Ada tools
21 * Consistent interface over different targets
22 * Automatic usage of the proper calling conventions
23 * Access to Ada constants and variables
24 * Definition of intrinsic routines
25 * Possibility of inlining a subprogram comprising assembler code
26 * Code optimizer can take Inline Assembler code into account
28 This appendix presents a series of examples to show you how to use
29 the Inline Assembler.  Although it focuses on the Intel x86,
30 the general approach applies also to other processors.
31 It is assumed that you are familiar with Ada
32 and with assembly language programming.
34 .. _Basic_Assembler_Syntax:
36 Basic Assembler Syntax
37 ======================
39 The assembler used by GNAT and gcc is based not on the Intel assembly
40 language, but rather on a language that descends from the AT&T Unix
41 assembler *as* (and which is often referred to as 'AT&T syntax').
42 The following table summarizes the main features of *as* syntax
43 and points out the differences from the Intel conventions.
44 See the gcc *as* and *gas* (an *as* macro
45 pre-processor) documentation for further information.
48 | *Register names*
49 |   gcc / *as*: Prefix with '%'; for example `%eax`
50 |   Intel: No extra punctuation; for example `eax`
53 | *Immediate operand*
54 |   gcc / *as*: Prefix with '$'; for example `$4`
55 |   Intel: No extra punctuation; for example `4`
58 | *Address*
59 |   gcc / *as*: Prefix with '$'; for example `$loc`
60 |   Intel: No extra punctuation; for example `loc`
63 | *Memory contents*
64 |   gcc / *as*: No extra punctuation; for example `loc`
65 |   Intel: Square brackets; for example `[loc]`
68 | *Register contents*
69 |   gcc / *as*: Parentheses; for example `(%eax)`
70 |   Intel: Square brackets; for example `[eax]`
73 | *Hexadecimal numbers*
74 |   gcc / *as*: Leading '0x' (C language syntax); for example `0xA0`
75 |   Intel: Trailing 'h'; for example `A0h`
78 | *Operand size*
79 |   gcc / *as*: Explicit in op code; for example `movw` to move a 16-bit word
80 |   Intel: Implicit, deduced by assembler; for example `mov`
83 | *Instruction repetition*
84 |   gcc / *as*: Split into two lines; for example
85 |     `rep`
86 |     `stosl`
87 |   Intel: Keep on one line; for example `rep stosl`
90 | *Order of operands*
91 |   gcc / *as*: Source first; for example `movw $4, %eax`
92 |   Intel: Destination first; for example `mov eax, 4`
95 .. _A_Simple_Example_of_Inline_Assembler:
97 A Simple Example of Inline Assembler
98 ====================================
100 The following example will generate a single assembly language statement,
101 `nop`, which does nothing.  Despite its lack of run-time effect,
102 the example will be useful in illustrating the basics of
103 the Inline Assembler facility.
105   .. code-block:: ada
107      with System.Machine_Code; use System.Machine_Code;
108      procedure Nothing is
109      begin
110         Asm ("nop");
111      end Nothing;
113 `Asm` is a procedure declared in package `System.Machine_Code`;
114 here it takes one parameter, a *template string* that must be a static
115 expression and that will form the generated instruction.
116 `Asm` may be regarded as a compile-time procedure that parses
117 the template string and additional parameters (none here),
118 from which it generates a sequence of assembly language instructions.
120 The examples in this chapter will illustrate several of the forms
121 for invoking `Asm`; a complete specification of the syntax
122 is found in the `Machine_Code_Insertions` section of the 
123 :title:`GNAT Reference Manual`.
125 Under the standard GNAT conventions, the `Nothing` procedure
126 should be in a file named :file:`nothing.adb`.
127 You can build the executable in the usual way:
129   ::
131      $ gnatmake nothing
132   
133 However, the interesting aspect of this example is not its run-time behavior
134 but rather the generated assembly code.
135 To see this output, invoke the compiler as follows:
137   ::
139      $  gcc -c -S -fomit-frame-pointer -gnatp nothing.adb
140   
141 where the options are:
143 * :samp:`-c`
144     compile only (no bind or link)
146 * :samp:`-S`
147     generate assembler listing
149 * :samp:`-fomit-frame-pointer`
150     do not set up separate stack frames
152 * :samp:`-gnatp`
153     do not add runtime checks
155 This gives a human-readable assembler version of the code. The resulting
156 file will have the same name as the Ada source file, but with a `.s`
157 extension. In our example, the file :file:`nothing.s` has the following
158 contents:
160   ::
162      .file "nothing.adb"
163      gcc2_compiled.:
164      ___gnu_compiled_ada:
165      .text
166         .align 4
167      .globl __ada_nothing
168      __ada_nothing:
169      #APP
170         nop
171      #NO_APP
172         jmp L1
173         .align 2,0x90
174      L1:
175         ret
177 The assembly code you included is clearly indicated by
178 the compiler, between the `#APP` and `#NO_APP`
179 delimiters. The character before the 'APP' and 'NOAPP'
180 can differ on different targets. For example, GNU/Linux uses '#APP' while
181 on NT you will see '/APP'.
183 If you make a mistake in your assembler code (such as using the
184 wrong size modifier, or using a wrong operand for the instruction) GNAT
185 will report this error in a temporary file, which will be deleted when
186 the compilation is finished.  Generating an assembler file will help
187 in such cases, since you can assemble this file separately using the
188 *as* assembler that comes with gcc.
190 Assembling the file using the command
192   ::
194      $ as nothing.s  
196 will give you error messages whose lines correspond to the assembler
197 input file, so you can easily find and correct any mistakes you made.
198 If there are no errors, *as* will generate an object file
199 :file:`nothing.out`.
202 .. _Output_Variables_in_Inline_Assembler:
204 Output Variables in Inline Assembler
205 ====================================
207 The examples in this section, showing how to access the processor flags,
208 illustrate how to specify the destination operands for assembly language
209 statements.
212   .. code-block:: ada
214      with Interfaces; use Interfaces;
215      with Ada.Text_IO; use Ada.Text_IO;
216      with System.Machine_Code; use System.Machine_Code;
217      procedure Get_Flags is
218         Flags : Unsigned_32;
219         use ASCII;
220      begin
221         Asm ("pushfl"          & LF & HT & -- push flags on stack
222              "popl %%eax"      & LF & HT & -- load eax with flags
223              "movl %%eax, %0",             -- store flags in variable
224              Outputs => Unsigned_32'Asm_Output ("=g", Flags));
225         Put_Line ("Flags register:" & Flags'Img);
226      end Get_Flags;
227   
228 In order to have a nicely aligned assembly listing, we have separated
229 multiple assembler statements in the Asm template string with linefeed
230 (ASCII.LF) and horizontal tab (ASCII.HT) characters.
231 The resulting section of the assembly output file is:
233   ::
235      #APP
236         pushfl
237         popl %eax
238         movl %eax, -40(%ebp)
239      #NO_APP
241 It would have been legal to write the Asm invocation as:
243   .. code-block:: ada
245      Asm ("pushfl popl %%eax movl %%eax, %0")
246   
247 but in the generated assembler file, this would come out as:
249   ::
251      #APP
252         pushfl popl %eax movl %eax, -40(%ebp)
253      #NO_APP
254   
255 which is not so convenient for the human reader.
257 We use Ada comments
258 at the end of each line to explain what the assembler instructions
259 actually do.  This is a useful convention.
261 When writing Inline Assembler instructions, you need to precede each register
262 and variable name with a percent sign.  Since the assembler already requires
263 a percent sign at the beginning of a register name, you need two consecutive
264 percent signs for such names in the Asm template string, thus `%%eax`.
265 In the generated assembly code, one of the percent signs will be stripped off.
267 Names such as `%0`, `%1`, `%2`, etc., denote input or output
268 variables: operands you later define using `Input` or `Output`
269 parameters to `Asm`.
270 An output variable is illustrated in
271 the third statement in the Asm template string:
273   ::
275      movl %%eax, %0
276   
277 The intent is to store the contents of the eax register in a variable that can
278 be accessed in Ada.  Simply writing `movl %%eax, Flags` would not
279 necessarily work, since the compiler might optimize by using a register
280 to hold Flags, and the expansion of the `movl` instruction would not be
281 aware of this optimization.  The solution is not to store the result directly
282 but rather to advise the compiler to choose the correct operand form;
283 that is the purpose of the `%0` output variable.
285 Information about the output variable is supplied in the `Outputs`
286 parameter to `Asm`:
288   .. code-block:: ada
290      Outputs => Unsigned_32'Asm_Output ("=g", Flags));
291   
292 The output is defined by the `Asm_Output` attribute of the target type;
293 the general format is
295   .. code-block:: ada
297      Type'Asm_Output (constraint_string, variable_name)
298   
299 The constraint string directs the compiler how
300 to store/access the associated variable.  In the example
302   .. code-block:: ada
304      Unsigned_32'Asm_Output ("=m", Flags);
305   
306 the `"m"` (memory) constraint tells the compiler that the variable
307 `Flags` should be stored in a memory variable, thus preventing
308 the optimizer from keeping it in a register.  In contrast,
310   .. code-block:: ada
312      Unsigned_32'Asm_Output ("=r", Flags);
313   
314 uses the `"r"` (register) constraint, telling the compiler to
315 store the variable in a register.
317 If the constraint is preceded by the equal character '=', it tells
318 the compiler that the variable will be used to store data into it.
320 In the `Get_Flags` example, we used the `"g"` (global) constraint,
321 allowing the optimizer to choose whatever it deems best.
323 There are a fairly large number of constraints, but the ones that are
324 most useful (for the Intel x86 processor) are the following:
326  ====== ==========================================
327  *=*    output constraint
328  *g*    global (i.e., can be stored anywhere)
329  *m*    in memory
330  *I*    a constant
331  *a*    use eax
332  *b*    use ebx
333  *c*    use ecx
334  *d*    use edx
335  *S*    use esi
336  *D*    use edi
337  *r*    use one of eax, ebx, ecx or edx
338  *q*    use one of eax, ebx, ecx, edx, esi or edi
339  ====== ==========================================
341 The full set of constraints is described in the gcc and *as*
342 documentation; note that it is possible to combine certain constraints
343 in one constraint string.
345 You specify the association of an output variable with an assembler operand
346 through the :samp:`%{n}` notation, where *n* is a non-negative
347 integer.  Thus in
349   .. code-block:: ada
351      Asm ("pushfl"          & LF & HT & -- push flags on stack
352           "popl %%eax"      & LF & HT & -- load eax with flags
353           "movl %%eax, %0",             -- store flags in variable
354           Outputs => Unsigned_32'Asm_Output ("=g", Flags));
355     
357 `%0` will be replaced in the expanded code by the appropriate operand,
358 whatever
359 the compiler decided for the `Flags` variable.
361 In general, you may have any number of output variables:
363 * Count the operands starting at 0; thus `%0`, `%1`, etc.
365 * Specify the `Outputs` parameter as a parenthesized comma-separated list
366   of `Asm_Output` attributes
368 For example:
370   .. code-block:: ada
372      Asm ("movl %%eax, %0" & LF & HT &
373           "movl %%ebx, %1" & LF & HT &
374           "movl %%ecx, %2",
375           Outputs => (Unsigned_32'Asm_Output ("=g", Var_A),   --  %0 = Var_A
376                       Unsigned_32'Asm_Output ("=g", Var_B),   --  %1 = Var_B
377                       Unsigned_32'Asm_Output ("=g", Var_C))); --  %2 = Var_C
378   
379 where `Var_A`, `Var_B`, and `Var_C` are variables
380 in the Ada program.
382 As a variation on the `Get_Flags` example, we can use the constraints
383 string to direct the compiler to store the eax register into the `Flags`
384 variable, instead of including the store instruction explicitly in the
385 `Asm` template string:
387   .. code-block:: ada
389      with Interfaces; use Interfaces;
390      with Ada.Text_IO; use Ada.Text_IO;
391      with System.Machine_Code; use System.Machine_Code;
392      procedure Get_Flags_2 is
393         Flags : Unsigned_32;
394         use ASCII;
395      begin
396         Asm ("pushfl"      & LF & HT & -- push flags on stack
397              "popl %%eax",             -- save flags in eax
398              Outputs => Unsigned_32'Asm_Output ("=a", Flags));
399         Put_Line ("Flags register:" & Flags'Img);
400      end Get_Flags_2;
401   
402 The `"a"` constraint tells the compiler that the `Flags`
403 variable will come from the eax register. Here is the resulting code:
405   ::
407      #APP
408         pushfl
409         popl %eax
410      #NO_APP
411         movl %eax,-40(%ebp)
412   
413 The compiler generated the store of eax into Flags after
414 expanding the assembler code.
416 Actually, there was no need to pop the flags into the eax register;
417 more simply, we could just pop the flags directly into the program variable:
419   .. code-block:: ada
421      with Interfaces; use Interfaces;
422      with Ada.Text_IO; use Ada.Text_IO;
423      with System.Machine_Code; use System.Machine_Code;
424      procedure Get_Flags_3 is
425         Flags : Unsigned_32;
426         use ASCII;
427      begin
428         Asm ("pushfl"  & LF & HT & -- push flags on stack
429              "pop %0",             -- save flags in Flags
430              Outputs => Unsigned_32'Asm_Output ("=g", Flags));
431         Put_Line ("Flags register:" & Flags'Img);
432      end Get_Flags_3;
433   
435 .. _Input_Variables_in_Inline_Assembler:
437 Input Variables in Inline Assembler
438 ===================================
440 The example in this section illustrates how to specify the source operands
441 for assembly language statements.
442 The program simply increments its input value by 1:
444   .. code-block:: ada
446      with Interfaces; use Interfaces;
447      with Ada.Text_IO; use Ada.Text_IO;
448      with System.Machine_Code; use System.Machine_Code;
449      procedure Increment is
451         function Incr (Value : Unsigned_32) return Unsigned_32 is
452            Result : Unsigned_32;
453         begin
454            Asm ("incl %0",
455                 Outputs => Unsigned_32'Asm_Output ("=a", Result),
456                 Inputs  => Unsigned_32'Asm_Input ("a", Value));
457            return Result;
458         end Incr;
460         Value : Unsigned_32;
462      begin
463         Value := 5;
464         Put_Line ("Value before is" & Value'Img);
465         Value := Incr (Value);
466        Put_Line ("Value after is" & Value'Img);
467      end Increment;
468   
469 The `Outputs` parameter to `Asm` specifies
470 that the result will be in the eax register and that it is to be stored
471 in the `Result` variable.
473 The `Inputs` parameter looks much like the `Outputs` parameter,
474 but with an `Asm_Input` attribute.
475 The `"="` constraint, indicating an output value, is not present.
477 You can have multiple input variables, in the same way that you can have more
478 than one output variable.
480 The parameter count (%0, %1) etc, still starts at the first output statement,
481 and continues with the input statements.
483 Just as the `Outputs` parameter causes the register to be stored into the
484 target variable after execution of the assembler statements, so does the
485 `Inputs` parameter cause its variable to be loaded into the register
486 before execution of the assembler statements.
488 Thus the effect of the `Asm` invocation is:
490 * load the 32-bit value of `Value` into eax
491 * execute the `incl %eax` instruction
492 * store the contents of eax into the `Result` variable
494 The resulting assembler file (with *-O2* optimization) contains:
496   ::
498      _increment__incr.1:
499         subl $4,%esp
500         movl 8(%esp),%eax
501      #APP
502         incl %eax
503      #NO_APP
504         movl %eax,%edx
505         movl %ecx,(%esp)
506         addl $4,%esp
507         ret
508   
510 .. _Inlining_Inline_Assembler_Code:
512 Inlining Inline Assembler Code
513 ==============================
515 For a short subprogram such as the `Incr` function in the previous
516 section, the overhead of the call and return (creating / deleting the stack
517 frame) can be significant, compared to the amount of code in the subprogram
518 body.  A solution is to apply Ada's `Inline` pragma to the subprogram,
519 which directs the compiler to expand invocations of the subprogram at the
520 point(s) of call, instead of setting up a stack frame for out-of-line calls.
521 Here is the resulting program:
523   .. code-block:: ada
525      with Interfaces; use Interfaces;
526      with Ada.Text_IO; use Ada.Text_IO;
527      with System.Machine_Code; use System.Machine_Code;
528      procedure Increment_2 is
530         function Incr (Value : Unsigned_32) return Unsigned_32 is
531            Result : Unsigned_32;
532         begin
533            Asm ("incl %0",
534                 Outputs => Unsigned_32'Asm_Output ("=a", Result),
535                 Inputs  => Unsigned_32'Asm_Input ("a", Value));
536            return Result;
537         end Incr;
538         pragma Inline (Increment);
540         Value : Unsigned_32;
542      begin
543         Value := 5;
544         Put_Line ("Value before is" & Value'Img);
545         Value := Increment (Value);
546         Put_Line ("Value after is" & Value'Img);
547      end Increment_2;
549 Compile the program with both optimization (*-O2*) and inlining
550 (*-gnatn*) enabled.
552 The `Incr` function is still compiled as usual, but at the
553 point in `Increment` where our function used to be called:
556   ::
558      pushl %edi
559      call _increment__incr.1
560   
561 the code for the function body directly appears:
564   ::
566      movl %esi,%eax
567      #APP
568         incl %eax
569      #NO_APP
570         movl %eax,%edx
572 thus saving the overhead of stack frame setup and an out-of-line call.
575 .. _Other_`Asm`_Functionality:
577 Other `Asm` Functionality
578 =========================
580 This section describes two important parameters to the `Asm`
581 procedure: `Clobber`, which identifies register usage;
582 and `Volatile`, which inhibits unwanted optimizations.
584 .. _The_`Clobber`_Parameter:
586 The `Clobber` Parameter
587 -----------------------
589 One of the dangers of intermixing assembly language and a compiled language
590 such as Ada is that the compiler needs to be aware of which registers are
591 being used by the assembly code.  In some cases, such as the earlier examples,
592 the constraint string is sufficient to indicate register usage (e.g.,
593 `"a"` for
594 the eax register).  But more generally, the compiler needs an explicit
595 identification of the registers that are used by the Inline Assembly
596 statements.
598 Using a register that the compiler doesn't know about
599 could be a side effect of an instruction (like `mull`
600 storing its result in both eax and edx).
601 It can also arise from explicit register usage in your
602 assembly code; for example:
604   .. code-block:: ada
606      Asm ("movl %0, %%ebx" & LF & HT &
607           "movl %%ebx, %1",
608           Outputs => Unsigned_32'Asm_Output ("=g", Var_Out),
609           Inputs  => Unsigned_32'Asm_Input  ("g", Var_In));
610   
611 where the compiler (since it does not analyze the `Asm` template string)
612 does not know you are using the ebx register.
614 In such cases you need to supply the `Clobber` parameter to `Asm`,
615 to identify the registers that will be used by your assembly code:
618   .. code-block:: ada
620      Asm ("movl %0, %%ebx" & LF & HT &
621           "movl %%ebx, %1",
622           Outputs => Unsigned_32'Asm_Output ("=g", Var_Out),
623           Inputs  => Unsigned_32'Asm_Input  ("g", Var_In),
624           Clobber => "ebx");
625   
626 The Clobber parameter is a static string expression specifying the
627 register(s) you are using.  Note that register names are *not* prefixed
628 by a percent sign. Also, if more than one register is used then their names
629 are separated by commas; e.g., `"eax, ebx"`
631 The `Clobber` parameter has several additional uses:
633 * Use 'register' name `cc` to indicate that flags might have changed
634 * Use 'register' name `memory` if you changed a memory location
637 .. _The_`Volatile`_Parameter:
639 The `Volatile` Parameter
640 ------------------------
642 .. index:: Volatile parameter
644 Compiler optimizations in the presence of Inline Assembler may sometimes have
645 unwanted effects.  For example, when an `Asm` invocation with an input
646 variable is inside a loop, the compiler might move the loading of the input
647 variable outside the loop, regarding it as a one-time initialization.
649 If this effect is not desired, you can disable such optimizations by setting
650 the `Volatile` parameter to `True`; for example:
652   .. code-block:: ada
654      Asm ("movl %0, %%ebx" & LF & HT &
655           "movl %%ebx, %1",
656           Outputs  => Unsigned_32'Asm_Output ("=g", Var_Out),
657           Inputs   => Unsigned_32'Asm_Input  ("g", Var_In),
658           Clobber  => "ebx",
659           Volatile => True);
660   
661 By default, `Volatile` is set to `False` unless there is no
662 `Outputs` parameter.
664 Although setting `Volatile` to `True` prevents unwanted
665 optimizations, it will also disable other optimizations that might be
666 important for efficiency. In general, you should set `Volatile`
667 to `True` only if the compiler's optimizations have created
668 problems.