Inline ASM ARM syntax to load immediate values with integrated assembler

Hi,

What would be the proper syntax in a C file, using inline assembly, to
load a immediate value into an ARM register using clang & integrated
assembler?

The following syntax is rejected by LLVM:

    // clang -target armv7em-none-eabi -mthumb

    #define CONSTANT 0x1234

    void __attribute__((naked))
    foo(void)
    {
       asm volatile (
          "ldr r0, =%0 \n"
          :
          :
          "X" (CONSTANT)
          :
          "r0"
       );
    }

“X” transforms the constant into a “#1234”, and LLVM does not seem to
accept “=#1234” syntax. I think the proper syntax should be “ldr r0,
=0x1234”, but I’ve been unable to find a constraint string that would
emit the constant w/o the dash prefix.

The “=%0” syntax is accepted by GCC - I’m not sure it is valid,
although I’m still looking for a comprehensive reference document for
such a syntax.

“mov r0, %0” could work for small encodable value, but not for the
whole 32-bit range where the pseudo-instruction “ldr r0, =constant" is
required.

Thanks.

Hello Emmanuel,

I've not been able to come up with anything that does exactly what you
want. I've put some comments inline.

Hi,

What would be the proper syntax in a C file, using inline assembly, to
load a immediate value into an ARM register using clang & integrated
assembler?

I don't think that there is a constraint that doesn't print the #. The
source code refers to a modifier 'c' that does not print the # however
that is rejected by clang. This was added very early on in the ARM
backend and there weren't any tests added so it is possible that it
has bitrotted. I'd be very happy to be proved wrong there.

If you can use constants directly then "ldr r0, =0x1234" will work. It
is possible although ugly to use macros such as:

void __attribute__((naked))
    foo(void)
    {
#define ASM(C) ASM_(C)
#define ASM_(C) \
       asm volatile ( \
          "ldr r0, =" #C "\n"\
          :\
          :\
          :\
          "r0"\
       );
       ASM(CONSTANT)
    }

There may be a much better way than that, but it is all I can think of
right now.

The following syntax is rejected by LLVM:

    // clang -target armv7em-none-eabi -mthumb

    #define CONSTANT 0x1234

    void __attribute__((naked))
    foo(void)
    {
       asm volatile (
          "ldr r0, =%0 \n"
          :
          :
          "X" (CONSTANT)
          :
          "r0"
       );
    }

“X” transforms the constant into a “#1234”, and LLVM does not seem to
accept “=#1234” syntax. I think the proper syntax should be “ldr r0,
=0x1234”, but I’ve been unable to find a constraint string that would
emit the constant w/o the dash prefix.

The “=%0” syntax is accepted by GCC - I’m not sure it is valid,
although I’m still looking for a comprehensive reference document for
such a syntax.

The ldr r0, = is a pseudo instruction originally implemented in armasm
I believe then in GNU as and then in the llvm integrated assembler.
Unfortunately the precise behaviour isn't written down and does vary
subtly between implementations. I think that it wouldn't be difficult
to change the assembly parser to optionally skip over the '#' as it
has to do that in several other places. May be worth a PR.

Peter

The 'c' modifier works:

 \#define CONSTANT 0x12345678

 void \_\_attribute\_\_\(\(naked\)\)
 foo\(void\)
 \{
    asm volatile \(
       "ldr r0, =%c0\\n"
       "b 1f\\n"
       "\.ltorg\\n"
       "1:\\n"
       :
       "i" \(CONSTANT\)
       :
       "r0"
    \);
 \}

Note that you must put an ".ltorg" directive into your inline assembly; otherwise, the constant might end up somewhere out of range.

If you're targeting armv6t2 or later, you can also just use movw/movt:

 \#define CONSTANT 0x12345678

 void \_\_attribute\_\_\(\(naked\)\)
 foo\(void\)
 \{
    asm volatile \(
       "movw r0, %0\\n"
       "movt r0, %1\\n"
       //"b 1f\\n"
       //"\.ltorg\\n"
       //"1:\\n"
       :
       "i" \(CONSTANT&0xFFFF\),
       "i" \(CONSTANT>>16\)
       :
       "r0"
    \);
 \}

-Eli

Thanks for your help Peter & Eli, it works smoothly.