我想使用开源工具来玩新的ARM SVE instructions。
首先,我想整理一下出现在https://developer.arm.com/docs/dui0965/latest/getting-started-with-the-sve-compiler/assembling-sve-code
上的最小示例。// example1.s
.global main
main:
mov x0, 0x90000000
mov x8, xzr
ptrue p0.s //SVE instruction
fcpy z0.s, p0/m, #5.00000000 //SVE instruction
orr w10, wzr, #0x400
loop:
st1w z0.s, p0, [x0, x8, lsl #2] //SVE instruction
incw x8 //SVE instruction
whilelt p0.s, x8, x10 //SVE instruction
b.any loop //SVE instruction
mov w0, wzr
ret
但是,当我在Ubuntu 16.04上尝试时:
sudo apt-get install binutils-aarch64-linux-gnu
aarch64-linux-gnu-as example1.S
它不识别任何SVE组装说明,例如:
example1.S:6: Error: unknown mnemonic `ptrue' -- `ptrue p0.s'
我认为这是因为我的GNU AS 2.26.1太旧了,还没有SVE支持。
我也可以使用LLVM或任何其他开源汇编程序。
一旦我设法进行汇编,那么我想从3.0.0 has SVE support开始在QEMU用户模式下运行它。
答案 0 :(得分:0)
带有断言的自动化示例
下面,我描述了该示例的实现方式。
组装
Ubuntu 18.04中的aarch64-linux-gnu-as
2.30对于SVE来说已经足够新了,可以从以下位置看到:https://sourceware.org/binutils/docs-2.30/as/AArch64-Extensions.html#AArch64-Extensions
否则,在Ubuntu 16.04上很容易从源代码编译Binutils,只需这样做:
git clone git://sourceware.org/git/binutils-gdb.git
cd binutils-gdb
# master that I tested with.
git checkout 4de5434b694fc260d02610e8e7fec21b2923600a
./configure --target aarch64-elf --prefix "$(pwd)/ble"
make -j `nproc`
make install
我没有签出标签,因为最后一个标签已经使用了几个月,而且我不希望在引入SVE时对日志消息进行grep;-)
然后使用编译的as
并在Ubuntu 16.04上与打包的GCC链接:
./binutils-gdb/ble/bin/aarch64-elf-as -c -march=armv8.5-a+sve \
-o example1.o example1.S
aarch64-linux-gnu-gcc -march=armv8.5-a -nostdlib -o example1 example1.o
在Ubuntu 16.04上,aarch64-linux-gnu-gcc
5.4没有-march=armv8.5-a
,因此只需使用-march=armv8-a
,就可以了。无论如何,Ubuntu 16.04和18.04都没有-march=armv8-a+sve
,它是到达时的最佳选择。
或者,您也可以将以下内容添加到-march=armv8.5-a+sve
源代码的开头,而不是传递.S
:
.arch armv8.5-a+sve
QEMU模拟
在How to single step ARM assembly in GDB on QEMU?
上说明了在QEMU上逐步调试它的过程。首先,我将示例制作成一个最小的自包含Linux可执行文件:
.data
x: .double 1.5, 2.5, 3.5, 4.5
y: .double 5.0, 6.0, 7.0, 8.0
y_expect: .double 8.0, 11.0, 14.0, 17.0
a: .double 2.0
n: .word 4
.text
.global _start
_start:
ldr x0, =x
ldr x1, =y
ldr x2, =a
ldr x3, =n
bl daxpy
/* exit */
mov x0, #0
mov x8, #93
svc #0
/* Multiply by a scalar and add.
*
* Operation:
*
* Y += a * X
*
* C signature:
*
* void daxpy(double *x, double *y, double *a, int *n)
*
* The name "daxpy" comes from LAPACK:
* http://www.netlib.org/lapack/explore-html/de/da4/group__double__blas__level1_ga8f99d6a644d3396aa32db472e0cfc91c.html
*
* Adapted from: https://alastairreid.github.io/papers/sve-ieee-micro-2017.pdf
*/
daxpy:
ldrsw x3, [x3]
mov x4, #0
whilelt p0.d, x4, x3
ld1rd z0.d, p0/z, [x2]
.loop:
ld1d z1.d, p0/z, [x0, x4, lsl #3]
ld1d z2.d, p0/z, [x1, x4, lsl #3]
fmla z2.d, p0/m, z1.d, z0.d
st1d z2.d, p0, [x1, x4, lsl #3]
incd x4
whilelt p0.d, x4, x3
b.first .loop
ret
您可以通过以下方式运行它:
qemu-aarch64 -L /usr/aarch64-linux-gnu -E LD_BIND_NOW=1 ./example1
然后它很好地退出。
接下来,我们可以逐步调试以确认总和是真的:
qemu-aarch64 -g 1234 -L /usr/aarch64-linux-gnu -E LD_BIND_NOW=1 ./example1
和:
./binutils-gdb/ble/bin/aarch64-elf-gdb -ex 'file example1' \
-ex 'target remote localhost:1234' -ex 'set sysroot /usr/aarch64-linux-gnu'
现在,在bl daxpy
之后右上,然后运行:
>>> p (double[4])y_expect
$1 = {[0] = 8, [1] = 11, [2] = 14, [3] = 17}
>>> p (double[4])y
$2 = {[0] = 8, [1] = 11, [2] = 14, [3] = 17}
确认总和确实按照预期完成。
观察SVE寄存器似乎未实现,因为我在https://github.com/qemu/qemu/tree/v3.0.0/gdb-xml下找不到任何内容,但是通过复制其他FP寄存器来实现它应该不会太难吗?在以下位置提问:http://lists.nongnu.org/archive/html/qemu-discuss/2018-10/msg00020.html
您目前可以通过执行以下操作来部分或间接地观察它:
i r d0 d1 d2
因为SVE寄存器zX
的第一个条目与旧的vX
FP寄存器共享,但我们根本看不到p
。