GCC ARM汇编宏中的表达式

时间:2014-11-08 03:49:49

标签: gcc assembly macros arm neon

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

.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

构建上述结果会出现错误消息:预期的氖双精度或四精度寄存器 - “vld1.8 {d”0“,d”0 + 1“},[r0]'

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

提前致谢。

1 个答案:

答案 0 :(得分:2)

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