Keil Logo

ARMCLANG: Declare SVC function within ARMCLANG


Information in this knowledgebase article applies to:

  • MDK v5.x
  • ARMCLANG compiler v6.x and newer versions

QUESTION

Within ARMCC v5.x compiler, I can use the function qualifier __svc to declare a SuperVisor Call (SVC) function that takes up to four integer-like arguments. According to Arm Compiler Migration and Compatibility Guide, the function qualifier keyword __svc is not supported by ARMCLANG v6.x compiler.

How can I declare a SVC function with four arguments using ARMCLANG v6.x compiler?

ANSWER

Within ARMCLANG v6.x compiler inline assembly instructions can be used for this purpose.

To write inline assembly code with multiple instructions, you need to write them in the same __asm statement. Otherwise, compiler cannot guarantee that no extra instructions will be added between any two individual __asm statements.

In order to perform the supervisor call, e.g. with four arguments, you can write an inline assembly function as follows:

foo.c:

__attribute__((always_inline)) void svc_ahbCommand(ahbCommand,
                                                   sec_level,
                                                   start_address,
                                                   end_address)
{
    register unsigned r0 asm("r0") = ahbCommand;
    register unsigned r1 asm("r1") = sec_level;
    register unsigned r2 asm("r2") = start_address;
    register unsigned r3 asm("r3") = end_address;
    __asm volatile(
        "SVC #1"
        :
        : "r" (r0), "r" (r1), "r" (r2), "r" (r3)
    );
}

void foo(void)
{
    svc_ahbCommand(0x1, 0x2, 0x3, 0x4);
    svc_ahbCommand(0x5, 0x6, 0x7, 0x8);
}

In this implementation:

  • svc_ahbCommand() is a function containing statements with the register keyword to specify which registers to use for the function parameters, and an __asm statement containing the SVC instruction and the registers used for the function parameters.
  • svc_ahbCommand() is annotated with __attribute__((always_inline)), so that compiler is indicated that this function should always be inlined wherever possible, to avoid needing to branch to the function.
  • foo() contains multiple function calls to svc_ahbCommand().

When this example is built with:

armclang --target=arm-arm-none-eabi -march=armv7-m -O1 -c foo.c -o foo.o

The compiler generates code that moves the function parameters to registers R0-R3, and then inserts the SVC instruction inline, for both calls to svc_ahbCommand(), as can be seen in the output from the fromelf utility, such as:

fromelf --text -c foo.o

** Section #6

    Name        : .text.foo
...
    foo
        0x00000000:    2001        .       MOVS     r0,#1
        0x00000002:    2102        .!      MOVS     r1,#2
        0x00000004:    2203        ."      MOVS     r2,#3
        0x00000006:    2304        .#      MOVS     r3,#4
        0x00000008:    df01        ..      SVC      #0x1 ; formerly SWI
        0x0000000a:    2005        .       MOVS     r0,#5
        0x0000000c:    2106        .!      MOVS     r1,#6
        0x0000000e:    2207        ."      MOVS     r2,#7
        0x00000010:    2308        .#      MOVS     r3,#8
        0x00000012:    df01        ..      SVC      #0x1 ; formerly SWI
        0x00000014:    4770        pG      BX       lr

In this way, efficient code can be generated to make a supervisor call, using inline assembly statements within Arm Compiler 6.

MORE INFORMATION

Last Reviewed: Thursday, November 26, 2020


Did this article provide the answer you needed?
 
Yes
No
Not Sure
 
  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.