Cortex M0 :Inline assembly creates compilation problems

Asked by Prakash K Balasubramanian

While trying to compile the following piece of code written for Cortex-M0, GCC 4.6 (optimization level 0) throws up the following error message:

../SRC/rt_CMSIS.c:530:1: error: r7 cannot be used in asm here

The code snippet is:
__attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void)
{
  uint32_t result;

  __ASM volatile ("MRS %0, control" : "=r" (result) );
  return(result);
}

When compiled with optimization level 2, the error is gone.

Is this a known problem?

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
Prakash K Balasubramanian
Solved:
Last query:
Last reply:
Revision history for this message
Terry Guo (terry.guo) said :
#1

This error message is generated by gnu assembler, not the compiler. I just tried and found that the latest assembler hasn't this issue. So it may be a known bug of assembler. Let me find which patch fixed this issue and back port it to our upcoming release. Thank you for reporting it.

Revision history for this message
Terry Guo (terry.guo) said :
#2

Sorry for making above quick decision. This error message indeed comes from compiler.

Revision history for this message
Joey Ye (jinyun-ye) said :
#3

Change =r to =l. Msr doesn't accept r8 to r14. =l means r0 - r7
On Mar 6, 2013 2:35 PM, "Prakash K Balasubramanian" <
<email address hidden>> wrote:

> New question #223522 on GCC ARM Embedded:
> https://answers.launchpad.net/gcc-arm-embedded/+question/223522
>
>
> While trying to compile the following piece of code written for Cortex-M0,
> GCC 4.6 (optimization level 0) throws up the following error message:
>
> ../SRC/rt_CMSIS.c:530:1: error: r7 cannot be used in asm here
>
> The code snippet is:
> __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t
> __get_CONTROL(void)
> {
> uint32_t result;
>
> __ASM volatile ("MRS %0, control" : "=r" (result) );
> return(result);
> }
>
> When compiled with optimization level 2, the error is gone.
>
> Is this a known problem?
>
>
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Prakash K Balasubramanian (prakash-balasubramanian) said :
#4

But the error message is related to R7. So in a way, r is set to 1.

error: r7 cannot be used in asm here

Revision history for this message
Joey Ye (jinyun-ye) said :
#5

Sorry I was stupidly wrong. There must be some other problem.

- Joey

On Wed, Mar 6, 2013 at 4:35 PM, Prakash K Balasubramanian <
<email address hidden>> wrote:

> Question #223522 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/223522
>
> Status: Answered => Open
>
> Prakash K Balasubramanian is still having a problem:
> But the error message is related to R7. So in a way, r is set to 1.
>
> error: r7 cannot be used in asm here
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Terry Guo (terry.guo) said :
#6

Hi Joey,
Not the same issue we met before. It's R7 in the error message. The instruction "MRS r7, control" is a valid instruction.

Hi Prakash,
For Thumb-1 cores like m0, the R7 is used as a hard frame point register. In O0 level, the function's normal local variable is stored in stack and will be accessed via [R7+offset]. R7 works just like SP register. So any inline assembly code which is trying to modify/clobber the R7 is an offending instruction, GCC will generate the above error message for such case. This is a reasonable behavior. If you add gcc option -fomit-frame-pointer, this error will disappear. In O2 level, the local variable will be put into register or optimized out, the hard frame pointer register R7 isn't needed and can be used for general purpose. Thus no such error.

So the root cause for your issue is that the R7 is clobbering somewhere in your code. I can't reproduce this error just from the code snippet. I guess you have code like below:

register uint32_t m asm("r7");
m = __get_CONTROL();

Can you reduce your project to a small and repeatable case?

Revision history for this message
Prakash K Balasubramanian (prakash-balasubramanian) said :
#7

Hi Terry.

Output of __get_CONTROL() is assigned to local/global variable. Output is not assigned to a dedicated register.

As a workaround, I can add -fomit-frame-pointer.

What last stable+released version of the toolchain may I migrate to in order to avoid this workaround? Please advise.

Revision history for this message
Joey Ye (jinyun-ye) said :
#8

Prakash,

Not being able to reproduce the error we can hardly root cause and fix
compiler/CMSIS. Also if not root caused it might fail in some other cases.

So it is highly appreciated to reduce case to reproduce the error. Can you
please do it as a favor?

Thanks - Joey

On Wed, Mar 6, 2013 at 5:15 PM, Prakash K Balasubramanian <
<email address hidden>> wrote:

> Question #223522 on GCC ARM Embedded changed:
> https://answers.launchpad.net/gcc-arm-embedded/+question/223522
>
> Prakash K Balasubramanian posted a new comment:
> Hi Terry.
>
> Output of __get_CONTROL() is assigned to local/global variable. Output
> is not assigned to a dedicated register.
>
> As a workaround, I can add -fomit-frame-pointer.
>
> What last stable+released version of the toolchain may I migrate to in
> order to avoid this workaround? Please advise.
>
> --
> You received this question notification because you are an answer
> contact for GCC ARM Embedded.
>

Revision history for this message
Terry Guo (terry.guo) said :
#9

Hi Prakash,

This is not a gcc bug. Even for gcc trunk, this message still can be triggered when the r7 is modified. So no stable+released tool chain can be used. Below case can trigger this error message too:

terguo01@terry-pc01:47-debuggable$ arm-none-eabi-gcc -mthumb -mcpu=cortex-m0 -S n.c
n.c: In function 'foo':
n.c:8:1: error: r7 cannot be used in asm here
terguo01@terry-pc01:47-debuggable$ cat n.c
int foo ()
{
  register int m asm("r7");

  m = 0;

  return m;
}
terguo01@terry-pc01:47-debuggable$

The root cause is local variable m is in stack and will be accessed by [r7+0]. Meanwhile m is forced to use register r7. The m=0 causes the change to r7. So gcc complains. This is not a bug.

I suggest you to have a wider check on your code, not just force on function __get_CONTROL. You might find similar usage. By default GCC won't generate code which will modify the R7 when R7 is used as frame pointer.

If you can provide a case which can trigger this message but not modify r7, we can say gcc has a bug here.

Revision history for this message
Terry Guo (terry.guo) said :
#10

We can check this issue privately, if your code is not ready to public. I am glad to provide help. My email is <email address hidden>.

Revision history for this message
Prakash K Balasubramanian (prakash-balasubramanian) said :
#11

Hi Terry and Joey.
Yes, everything is falling into place now. We DO have a case where R7 is used in inline assembly.

So I confirm this is NOT a gcc bug. Your explanation is accurate and reconciles with my observation.

Thanks so much.