compile error with "Error: lo register required"

Asked by JiachengWang

there is a simple delay function as:

 extern void inline
__attribute__((__gnu_inline__,__always_inline__))
nrf_delay_tick(uint32_t volatile number_of_tick)
{
  __ASM volatile (
      "1:\tSUB %0, %0, #1\n\t"
      "BNE 1b\n\t"
      : "+r"(number_of_tick)
  );
}

when compile the code with "-O0", it is compiled successfully. But with "-O3", it has error with message as:
C:\Users\JIACHE~1\AppData\Local\Temp\ccqNWntY.s: Assembler messages:
C:\Users\JIACHE~1\AppData\Local\Temp\ccqNWntY.s:1404: Error: lo register required -- `sub fp,fp,#1'
lto-wrapper: C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2014q4/bin/arm-none-eabi-gcc returned 1 exit status
c:/program files (x86)/gnu tools arm embedded/4.9 2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/bin/ld.exe: lto-wrapper failed
collect2.exe: error: ld returned 1 exit status
make: *** [_build/wireless_sim_me_gcc_xxaa.out] 错误 1

How to fix this error? Thanks a lot.

Question information

Language:
English Edit question
Status:
Solved
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Solved by:
JiachengWang
Solved:
Last query:
Last reply:
Revision history for this message
jdobry (jdobry) said :
#1

First: your code is buggy. You need to update conditional flags for BNE. This mean, that you need SUBS instruction, not SUB.

And second if you need force to use "lo" register, don't use "r" but "l" like this:

__ASM volatile (
      "1:\tSUBS %0, %0, #1\n\t"
      "BNE 1b\n\t"
      : "+l"(number_of_tick)
  );

see to http://www.ethernut.de/en/documents/arm-inline-asm.html

Revision history for this message
JiachengWang (jiacheng123-wang) said :
#2

Hi jdobry,

Thanks a lot for you help.

Yes, with changing "+r" to "+l" the error is fixed, both "-O0" and "-O3" can be compiled successfully. but "SUBS" instruction has error with message "Error: instruction not supported in Thumb16 mode -- `subs r3,r3,#1'", so i till use "SUB".

Best Regards,

Jiacheng

Revision history for this message
jdobry (jdobry) said :
#3

Again, your code is buggy. Realy.
Combibation of SUBS and BNE is possible to use in ARM mode, not in thumb. Thumb code need to add IT instruction or better use this code:
__ASM volatile (
      "1:\tSUB %0, %0, #1\n\t"
      "CBNZ %0, 1b\n\t"
      : "+l"(number_of_tick)
  );

Reason is simple, conditions in Thumb code depent to previous IT helper instruction.

Revision history for this message
JiachengWang (jiacheng123-wang) said :
#4

Sorry, I'm new to ARM embedded. The chip I used is Cortex M0 based (Nordic nRF 51822).

With the code you suggested:
__ASM volatile (
       "1:\tSUB %0, %0, #1\n\t"
       "CBNZ %0, 1b\n\t"
       : "+l"(number_of_tick)
   );

there is a compiling error "Error: selected processor does not support Thumb mode `cbnz r3,1b'". The compile line is as:

"C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2014q4/bin/arm-none-eabi-gcc" -mcpu=cortex-m0 -DNRF51 -DBOARD_PCA10001 -DNRF51822_QFAA_CA --std=gnu99 -mthumb -Wall -Werror -mfloat-abi=soft -ffunction-sections -fdata-sections -fno-strict-aliasing -flto -fno-builtin -DNDEBUG -O3 -I"../include" -I"../include/gcc" -c -o _build/nrf_delay.o ../source/nrf_delay.c
"C:/Program Files (x86)/GNU Tools ARM Embedded/4.9 2014q4/bin/arm-none-eabi-gcc" -Xlinker -Map=_build/wireless_sim_me_gcc_xxaa.map -mcpu=cortex-m0 -L ./ -Tgcc_nrf51_blank_xxaa.ld -mthumb --specs=nosys.specs --specs=nano.specs _build/wireless_sim_me.o _build/simple_uart.o _build/radio_config.o _build/nrf_delay.o _build/sim_file_structure.o _build/transmission_protocol.o _build/card_reader.o _build/main_test.o _build/system_nrf51.o _build/gcc_startup_nrf51.o -o _build/wireless_sim_me_gcc_xxaa.out

Does this mean the chip I used only support ARM mode, not Thrumb mode? (With combination "SUB" and "BNE", the code is compiled successfully and running in the chip)

Thanks and Best Regards,

Jiacheng

Revision history for this message
jdobry (jdobry) said :
#5

You are right. M0 doesn't support CBNZ. (I usualy use bigger cores Cortex-R4,R5)
Therefore SUBS and BNE combination is correct.
Problem is that M0 doesn't support SUB istruction for target different from PC. It support only SUBS.
It looks loke some incompatibility of compiler to ARM documentation for M0 cores.

See to http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0432c/CHDCICDF.html

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#6

Hi Jiacheng,

If compiling for Thumb-1 (Cortex-M0+, Cortex-M0, Cortex-M1), sub will work as only subs is supported by these target and thus subs will actually be used. If you plan to use this code on other target at some point, you can add ".syntax unified\n\t" as the first instruction of inline assembly which will tell the assembler that the code is in ARM unified syntax and it will then allow you to use SUBS.

Best regards,

Thomas

Revision history for this message
JiachengWang (jiacheng123-wang) said :
#7

Thanks, Thomas,

Your help is very useful for my project.

Best regards,

Jiacheng