GCC ARM 汇编宏中的表达式

Posted

技术标签:

【中文标题】GCC ARM 汇编宏中的表达式【英文标题】:Expression in GCC ARM assembly macro 【发布时间】:2014-11-08 03:49:48 【问题描述】:

我需要涉及许多寄存器的宏,例如:

.macro load128bytes
  vld1.8 d0, d1, d2, d3, [r0]!
  vld1.8 d4, d5, d6, d7, [r0]!
  vld1.8 d8, d9, d10, d11, [r0]!
  vld1.8 d12, d13, d14, d15, [r0]!
.endm

如您所见,寄存器是连续的。但是,我想将起始寄存器的数量作为参数传递,例如:

.macro load128bytes srn
  vld1.8 d\srn, d\srn+1, d\srn+2, d\srn+3, [r0]!
  vld1.8 d\srn+4, d\srn+5, d\srn+6, d\srn+7, [r0]!
  vld1.8 d\srn+8, d\srn+9, d\srn+10, d\srn+11, [r0]!
  vld1.8 d\srn+12, d\srn+13, d\srn+14, d\srn+15, [r0]!
.endm

当然,上面的方法是行不通的。汇编器将它们解释为:d0, d0+1, d0+2, d0+3 而不是 d0, d1, d2, d3 当 srn 为 0 时我想要它们。

我在网上搜索了一个可以解决此问题的示例:

.macro  sum from=0, to=5
  .long   \from
  .if     \to-\from
    sum     "(\from+1)",\to
  .endif
.endm

虽然上面的例子运行良好,但它并没有帮助解决我的问题:

.macro  test    srn0
  vld1.8        d"(\srn0)", d"(\srn0+1)", [r0]
.endm

上述构建会导致错误消息:Neon double or quad precision register expected -- `vld1.8 d"0",d"0+1",[r0]'

有什么想法吗?每次传递多达 16 个寄存器真的很令人沮丧,更糟糕的是,它使我的代码容易出错。

提前致谢。

【问题讨论】:

【参考方案1】:

sum 示例之所以有效,是因为它给出了以下输出:

.long 0
.long (0+1)
.long ((0+1)+1)
.long (((0+1)+1)+1)
.long ((((0+1)+1)+1)+1)
.long (((((0+1)+1)+1)+1)+1)

因此,在宏扩展之后,汇编器在它期望表达式的地方看到表达式,并计算它们。您需要的技巧是让它在它期望表达式的地方评估表达式,并在程序集传递之前这样做。 alternate macro mode 和 CPP 样式的宏链接(为清晰起见,使用较小的示例)来提供帮助:

.macro _load32bytes base r0 r1 r2 r3
  vld1.8 d\r0, d\r1, d\r2, d\r3, [\base]!
.endm

.macro load32bytes srn
.altmacro
  _load32bytes r0, %(\srn), %(\srn+1), %(\srn+2), %(\srn+3)
.endm

% 运算符允许在宏扩展期间任意将表达式评估为字符串 - 我似乎无法说服它在单个宏中工作,但链接可以完成这项工作:

$ arm-linux-gnueabihf-as -alm -mfpu=neon test.s
ARM GAS  test.s                         page 1


   1                    .macro _load32bytes base r0 r1 r2 r3
   2                      vld1.8 d\r0, d\r1, d\r2, d\r3, [\base]!
   3                    .endm
   4
   5                    .macro load32bytes srn
   6                    .altmacro
   7                      _load32bytes r0, %(\srn), %(\srn+1), %(\srn+2), %(\srn+3)
   8                    .endm
   9
  10                    load32bytes 0
  10                    > .altmacro
  10                    >  _load32bytes r0,%(0),%(0+1),%(0+2),%(0+3)
  10 0000 0D0220F4      >>  vld1.8 d0,d1,d2,d3,[r0]!
  11                    load32bytes 3
  11                    > .altmacro
  11                    >  _load32bytes r0,%(3),%(3+1),%(3+2),%(3+3)
  11 0004 0D3220F4      >>  vld1.8 d3,d4,d5,d6,[r0]!
  12

【讨论】:

像魅力一样工作!非常感谢你。顺便说一句,我目前正在从事一个大型开源项目,该项目由纯手工制作的 NEON 组装例程和一本关于 ARM 优化的电子书组成。他们完成后我会告诉你的。当然,您将收到该电子书的免费“副本”。 :)

以上是关于GCC ARM 汇编宏中的表达式的主要内容,如果未能解决你的问题,请参考以下文章

ARM嵌入式开发中的GCC内联汇编__asm__

arm gcc 内嵌汇编,gcc该是啥选项呢

GCC 内联汇编错误:表达式后出现垃圾 `(%ebp)+4'

gcc内嵌汇编简介

使用 LLDB API 获取使用 ARM-GCC 编译的 elf 文件中表达式的地址

嵌入式:ARM 汇编控制伪操作