dear arm,
Is there a more detailed document that introduces how to use assembly and intrinsics in C code?
I found a breif introduction in migration_and_compatibility_guide_v6.18. But after reading it, I still don't know how to modify the format to meet Arm Compiler 6' requirements .
The code blow shows the example in migration_and_compatibility_guide_v6.18:
// __asm in Arm Compiler 5 int add(int i, int j) { int res; __asm { ADD res, i, j SUB res, i, res } return res; } // __asm in Arm Compiler 6 int add(int i, int j) { int res = 0; __asm ( "ADD %[result], %[input_i], %[input_j] \t\n" "SUB %[result], %[input_i], %[result] \t\n" : [result] "=&r" (res) : [input_i] "r" (i), [input_j] "r" (j) ); return res; }
But how should I modify the code below to meet Arm Compiler 6's requirements?
MOV sum, var1, LSL #16 QADD sum, sum, temp MOV result, sum, ASR #16 MOV zero, #0 RSB var2_inv, var2, #0
many thanks!
Hello, I am unsure exactly what the above code does, it is seemingly part of a larger sequence, but I was able to compile the below:
int example(int var1, int var2) { int result, sum, temp=0, zero, var2_inv; __asm ( "MOV %[sum], %[input1], LSL #16 \t\n" "QADD %[sum], %[sum], %[temp] \t\n" "MOV %[result], %[sum], ASR #16 \t\n" "MOV %[zero], #0 \t\n" "RSB %[var2_inv],%[input2], #0 \t\n" : [result] "=r" (result), [sum] "=r" (sum), [temp] "=r" (temp), [zero] "=r" (zero), [var2_inv] "=r" (var2_inv) : [input1] "r" (var1), [input2] "r" (var2) ); return result; }
as:
example 0x00000000: ea4f4100 O..A LSL r1,r0,#16 0x00000004: fa82f181 .... QADD r1,r1,r2 0x00000008: ea4f4021 O.!@ ASR r0,r1,#16 0x0000000c: f04f0300 O... MOV r3,#0 0x00000010: f1c10c00 .... RSB r12,r1,#0 0x00000014: 4770 pG BX lr
Command line used:
armclang -c --target=arm-arm-none-eabi -mcpu=cortex-m7 -O2 example.c fromelf -c example.o > example.txt
The below documentation is more thorough than the Migration Guide:https://developer.arm.com/documentation/100748/0618/Using-Assembly-and-Intrinsics-in-C-or-C---Code/Writing-inline-assembly-code
I change QADD temp, L_var1, 0x00008000 to the code below:
__inline short AMR_ENCroung_round (long L_var1_ { long temp; short result; __asm ( "QADD %[temp], %[input], 0x00008000\t\n" "MOV %[result], %[temp], ASR #16\t\n" :[result] "=r" (result), [temp] "=r" (temp) :[input] "r" (L_var1) ); return result; }
and it goes wrong. The error is:
pplease help me to solve it, thanks.
QADD takes registers as operands, not immediate values (0x8000 above).
Does this fix your issue?
__asm ( "MOV %[temp], 0x8000\t\n" "QADD %[temp], %[input], %[temp]\t\n" "MOV %[result], %[temp], ASR #16\t\n" :[result] "=r" (result), [temp] "=r" (temp) :[input] "r" (L_var1) );
YES!
I have another question. How should I fix this error when using QSUBLT, RSBLT, SUBNE and so on: predicated instructions must be in IT block.
I assume you are using a Cortex-M processor? An IT (if-then) block is needed for such conditional execution:
https://developer.arm.com/documentation/dui0552/a/BABEHFEF
So your code would be something like the following (in raw assembler format)
IT LT ; execute one instruction (iT) if LT QSUBLT...
Or possibly
ITTE LT ; execute two instructions (iTTe)if LT QSUBLT ... MOVLT ... ; else QSUBGE ...
Got it!
How should I use CMP and TEQ with ASR/LSL? I wrote the code below and CMP instruction went wrong with: operand must be a register in range[r0, r15].
.... "CMP %[input1], %[result], ASR %[input2]\t\n" ... "IT LT\t\n" "MOVLT %[result], #0x80000000\t\n" ....
That is not a valid instruction. For Cortex-M, such a shift can only be specified with an immediate value.
I recommend you consult Arm Architecture Reference Manual for such syntax questions:https://developer.arm.com/documentation/ddi0403/latestIs there a reason you are using the inline assembler? This is typically only used in very special cases. Also using 'true' assembler can give more explicit messaging:
$ armclang -c -g -O1 --target=arm-arm-none-eabi -mcpu=cortex-m4 foo.S -masm=auto "foo.S", line 3: Error: A1872E: Shift by register not allowed 3 00000000 CMP r0, r1, ASR r2
We're using cortex-r processor in thumb mode. "MOV %[result], %[input1], LSL %[input2]\t\n" didn't bring errors.
This is similarly defined in the Arm Architecture for v7A and v7R:https://developer.arm.com/documentation/ddi0406/latest/
CMP only accepts immediate shift in Thumb state (see A8.8.38, T3 encoding).MOV can use a register as a shift (see A8.8.106).
CMP can use a register shift only when in Arm state (A8.8.39).
From earlier I thought you were using Cortex-M.For completeness, IT instruction described at A8.8.55 of this document.
I see!
One last question . The code below gives error message(ARM mode):
long func() { long t; long result=0; __asm ( "MRS %[t], CPSR\t\n" //MRS t, CPSR "BIC %[t], %[t], #0x08000000\t\n" //BIC t, t, #0x08000000 "MSR CPSR_f, %[t]\t\n" //MSR CPSR_f, t "AND %[result], %[t], #0x08000000\t\n" //AND result, t, #0x08000000 :[t] "=r" (t), [result] "=r" (result) ); return result; }
how should I use CPSR with inline assembler? Why AND instruction occuers unexpected token in operand?
Which compiler version are you using?
Testing with amclang 6.18, the above compiled without issue for me (both Arm and Thumb, Cortex-R4).
Arm: func 0x00000000: e10f1000 .... MRS r1,APSR ; formerly CPSR 0x00000004: e3c11302 .... BIC r1,r1,#0x8000000 0x00000008: e128f001 ..(. MSR APSR_nzcvq,r1 ; formerly CPSR_f 0x0000000c: e2010302 .... AND r0,r1,#0x8000000 0x00000010: e12fff1e ../. BX lr Thumb: func 0x00000000: f3ef8100 .... MRS r1,APSR ; formerly CPSR 0x00000004: f0216100 !..a BIC r1,r1,#0x8000000 0x00000008: f3818800 .... MSR APSR_nzcvq,r1 ; formerly CPSR_f 0x0000000c: f0016000 ...` AND r0,r1,#0x8000000 0x00000010: 4770 pG BX lr
I'm using armclang6.18, too.
C:/Program Files/ArmCompilerforEmbedded6.18/bin/armclang --target=arm-arm-none-eabi -mcpu=cortex-r5 -o1 -fno-short-enums -mno-unaligned-access -mlittle-endian -g -marm @build/qogirl6_pubcp_builddir/dep/record_C_MACRO_INC.txt -c -IC:/Program Files/ArmCompilerforEmbedded6.18/include MS_Ref/source/codec/record/src/mp3_encoder/src/mp3_enc_spec_scale.c -MF build/qogirl6_pubcp_builddir/dep/record/mp3_enc_spec_scale.d.tmp -o build/qogirl6_pubcp_builddir/obj/record/mp3_enc_spec_scale.o
What options are specified in the file?
@build/qogirl6_pubcp_builddir/dep/record_C_MACRO_INC.txt
These are just macro definitions and include paths. They should not affect the compilation. I'm sorry, but I don't understand why it works for me, but not for you. Can you copy the above source exactly and test? Perhaps there is a mistake in your original source?The following builds for me without error (both Arm and Thumb):
armclang --version ... Arm Compiler for Embedded 6.18 armclang -c --target=arm-arm-none-eabi -mcpu=cortex-r5 -o1 -fno-short-enums -mno-unaligned-access -mlittle-endian -g -marm cpsr.c armclang -c --target=arm-arm-none-eabi -mcpu=cortex-r5 -o1 -fno-short-enums -mno-unaligned-access -mlittle-endian -g -mthumb cpsr.c