我需要涉及许多寄存器的宏,例如:
.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个寄存器真的很令人沮丧,更糟糕的是,它使我的代码容易出错。
提前致谢。
答案 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