Emmanuel Blot via llvm-dev
2018-Aug-31 15:48 UTC
[llvm-dev] 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.
Peter Smith via llvm-dev
2018-Aug-31 17:27 UTC
[llvm-dev] Inline ASM ARM syntax to load immediate values with integrated assembler
Hello Emmanuel, I've not been able to come up with anything that does exactly what you want. I've put some comments inline. On 31 August 2018 at 16:48, Emmanuel Blot via llvm-dev <llvm-dev at lists.llvm.org> wrote:> 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> “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. > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Friedman, Eli via llvm-dev
2018-Aug-31 17:57 UTC
[llvm-dev] Inline ASM ARM syntax to load immediate values with integrated assembler
On 8/31/2018 10:27 AM, Peter Smith via llvm-dev wrote:> Hello Emmanuel, > > I've not been able to come up with anything that does exactly what you > want. I've put some comments inline. > > On 31 August 2018 at 16:48, Emmanuel Blot via llvm-dev > <llvm-dev at lists.llvm.org> wrote: >> 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.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 -- Employee of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project