【问题标题】:ELLCC embedded LLVM compilation fails with certain asm instructions against Thumb2 Cortex-M0ELLCC 嵌入式 LLVM 编译因针对 Thumb2 Cortex-M0 的某些 asm 指令而失败
【发布时间】:2016-03-13 08:51:43
【问题描述】:

在 Gnu G++ 中成功使用的已知有效指令在此处对 Freescale MKL16Z Cortex-M0+ Thumb2 造成了一些错误

代码:

/* 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));

编译命令:

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

提示赞赏!我想知道我是否可以使用更简单的指令将 asm 重写为某种东西……它似乎不喜欢立即值编码?我不擅长组装。

【问题讨论】:

  • 不幸的是,Cortex M0+ 没有(大多数)Thumb2 指令。你必须坚持使用 movs r0,#0 代替 mov r0,#0
  • 您不应该在r0 上声明一个破坏者,或者更好的是,首先要求addrr0 中? "r0" 约束有效吗?
  • @doynax:这不太对。 M0+ 仅支持 T2 的子集。
  • 您为什么要使用 Linux 目标来实现明显的裸机 CPU?看起来像是自找麻烦。

标签: c assembly arm embedded ellcc


【解决方案1】:

我认为编译器告诉的是该指令在Thumb中不存在,而只存在于ARM中。

在 Thumb 中,几乎所有数据处理指令都会更新标志。这意味着:

MOV r0, #0

不存在,而是:

MOVS r0, #0 ; Update NZCV flags

【讨论】:

  • 一些 thumb2 指令在这个 Cortex-M0+ 中可用,特别是这段代码被证明可以在 gnu c++ 编译器上工作
  • 这是因为 GCC 更加灵活,并且在您编写 ADD 时不会引发错误,而实际上它会执行更新标志的 ADDS。一些编译器认为这是一个错误。
【解决方案2】:

用 movs 替换 mov 和用 mvns 替换 mvn 可以编译。由于某种未知原因,该二进制文件比 g++ 大 6 倍。 LLVM 似乎还没有准确表示 Cortex-M0+ 设备上的可用指令。

【讨论】:

  • LLVM 在这里是准确的。问题是 Cortex M0+ 只支持非常有限的 Thumb2 指令子集,基本上是长分支和几个系统控制指令。详情请参阅infocenter.arm.com/help/topic/com.arm.doc.dui0662b/…
  • 由此看来,LLVM 汇编器只是使用较新的 Unified 语法,而您的 GCC 使用的是旧版 Thumb 语法(带有令人讨厌的隐式标志设置)。
猜你喜欢
  • 2020-03-22
  • 2019-02-09
  • 2015-09-15
  • 1970-01-01
  • 2015-06-22
  • 2021-12-07
  • 2020-08-21
  • 1970-01-01
  • 2019-07-06
相关资源
最近更新 更多