ARM assembly[6]: GCC inline assembly

     Inline assembly of GCC is often used in the Linux kernel code. The format of GCC inline assembly is as follows:

__asm__ __volatile__(command part: output part: input part: damage part:)

GCC inline assembly provides a template and some constraints on dealing with variables and registers.

  • Add % before the number in the instruction part, such as %0, %1, etc., to indicate the template operand that needs to use the register. If the instruction unit uses several different operands, it means that several variables need to be combined with registers.
  • The output section after the instruction section is used to describe the C language variables and constraints that can be modified in the instruction section. Each output constraint usually starts with "=" or "+", followed by a letter (indicating the operand type description), followed by constraints on variable binding, the output section may be empty. The sign "=" indicates that the modified operand has only writable properties, and the sign "+" indicates that the modified operand has only readable and writable properties.
  • The input part is used to describe the C language variables and constraints that can only be read in the instruction part. The parameters described in the input section are only read-only. Do not try to modify the content of the input parameters, because the GCC compiler assumes that the content of the parameters in the input section is consistent before and after inline assembly, and "=" or " cannot be used in the input section. +" constraints, otherwise the compiler will report an error. Alternatively, the input section can be empty.
  • Damaged sections generally end with a "memory" constraint. "memory" tells the GCC compiler that internal assembly code changed values ​​in memory. Forces the compiler to store all cached values ​​before executing this assembly code. The value is reloaded after the assembly code is executed to prevent out-of-order compilation. "CC" indicates that the embedded code has modified the relevant flag bits of the status register.

Implementation of arch_local_irq_save(void) in the kernel

<arch/arm64/include/asm/irqflags.h>


static inline unsigned long arch_local_irq_save(void)
{

        unsigned long flags;
        asm volatile(
               "mrs %0, daif"       //读取PSTAT寄存器中的DAIF域到flags的变量
               "msr  daifset, #2"   //关闭IRQ
               : "=r" (flags)
               :"memory"); 

        return flags;
}

First look at the output part, the %0 operand corresponds to "=r(flags)", that is, the flags variable, where "=" indicates that the attribute of the modified operand is write-only, and "r" indicates that a general-purpose register is used.

Next look at the input part, in the above example, the input part is empty, no parameters are specified, and finally look at the damage part, which ends with "memory".

This function is mainly used to save the DAIF field in the PSTATE register to the temporary variable flags, then close the IRQ, and then use % to represent the serial number of the parameter in the output and input parts, such as %0 for the first parameter, %1 for the first parameter Two parameters, in order to enhance the readability of the code, you can use the name of the assembly symbol instead of % to represent the operand, such as the add() function below

int add(int i,int j)
{
     int res = 0;
     
      asm volatile(

          "add %w[result],%w[input_i],%w[input_j]"
          :[result] "=r" (res)
          :[input_i] "r" (i), [input_j] "r" (j)
      );


      return res;
}

The above is an example of a very simple GCC inline assembly function. The main function is to add the values ​​of parameter i and parameter j and finally return the result. First look at the output part, where only one operand is defined, and "[result]" means definition An assembly symbol operand, the symbol name is result, which corresponds to "=r(res)", uses the res variable defined in the function, and corresponds to %w【result】in the assembly code, where w represents the 32-bit general-purpose register in ARM64 .

Looking at the input section, two operands are defined, which are also defined in the form of assembly symbol operands. The first assembly symbol operand is input_i, the corresponding function parameter is i, and the second assembly symbol operand is input_j , and the corresponding formal parameter is j.

  GCC inline assembly operands and modifiers

Operators and Modifiers illustrate
= Modified operands are write-only
+ The modified operand has readable and writable attributes
& Modified operands can only be output

Guess you like

Origin blog.csdn.net/wanglei_11/article/details/132555542