1

Instructions which are known to be valid, successfully used in Gnu G++ are causing some errors here against a Freescale MKL16Z Cortex-M0+ Thumb2

The code:

/* setup the stack before we attempt anything else
   skip stack setup if __SP_INIT is 0
   assume sp is already setup. */
__asm (
"mov r0,%0\n\t"
"cmp r0,#0\n\t"
"beq skip_sp\n\t"
"mov sp,r0\n\t"
"sub sp,#4\n\t"
"mov r0,#0\n\t"
"mvn r0,r0\n\t"
"str r0,[sp,#0]\n\t"
"add sp,#4\n\t"
"skip_sp:\n\t"
::"r"(addr));

the compile command:

ecc -target thumb-linux-engeabi -mtune=cortex-m0plus -mcpu=cortex-m0plus -mthumb -O2 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -Wall -Wconversion -Wpointer-arith -Wshadow -Wfloat-equal  -g3 -I"[redacted]" -I"[redacted]" -I"[redacted]" -I"[redacted]" -std=c99 -MMD -MP -MF"Project_Settings/Startup_Code/startup.d" -MT"Project_Settings/Startup_Code/startup.o" -c -o "Project_Settings/Startup_Code/startup.o" "../Project_Settings/Startup_Code/startup.c"
../Project_Settings/Startup_Code/startup.c:209:17: error: instruction requires: arm-mode
    "sub sp,#4\n\t"
                ^
<inline asm>:6:2: note: instantiated into assembly here
        mov r0,#0
        ^
../Project_Settings/Startup_Code/startup.c:210:17: error: invalid instruction
    "mov r0,#0\n\t"
                ^
<inline asm>:7:2: note: instantiated into assembly here
        mvn r0,r0
        ^~~
2 errors generated.
make: *** [Project_Settings/Startup_Code/startup.o] Error 1

Tips appreciated! I wonder if I can rewrite the asm into something using simpler instructions… it doesn’t seem to like immediate value encoding? I’m not skilled with assembly.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Jacob Jennings
  • 2,796
  • 1
  • 24
  • 26

2 Answers2

4

I think that what the compiler tells is that the instruction does not exist in Thumb and only exists in ARM.

In Thumb, almost all data-processing instructions update the flags. It means that:

MOV r0, #0

Does not exist, but is instead:

MOVS r0, #0 ; Update NZCV flags
Dric512
  • 3,525
  • 1
  • 20
  • 27
  • Some thumb2 instructions are available in this Cortex-M0+, and this code in particular is proven working on gnu c++ compiler – Jacob Jennings Mar 13 '16 at 09:25
  • 2
    This is because GCC is more flexible, and does not raise an error when you write `ADD`, while it will actually execute an `ADDS` which updates the flags. Some compilers consider it as an error. – Dric512 Mar 13 '16 at 19:34
0

Replacing mov with movs and mvn with mvns got things compiling. The binary was 6 times larger than g++ for some unknown reason. It seems that LLVM does not yet have an accurate representation of available instructions on Cortex-M0+ devices.

Jacob Jennings
  • 2,796
  • 1
  • 24
  • 26
  • LLVM is accurate here. The issue is that Cortex M0+ only supports an exceedingly limited subset of Thumb2 instructions, basically long branches and a couple of system control instructions. See http://infocenter.arm.com/help/topic/com.arm.doc.dui0662b/BABIHJGA.html for specifics. – doynax Mar 13 '16 at 09:29
  • 2
    From that, it sounds a lot more like the LLVM assembler is simply using the newer Unified syntax, and your GCC is using the legacy Thumb syntax (with nasty implicit flag-setting). – Notlikethat Mar 13 '16 at 11:04