Zhiyuan zhu · 2019年11月13日

AARCH64 开发系列1: AARCH64 环境搭建

概述

近年来 Arm 服务器的发展势头很猛,但大部分人的个人电脑还是 x86 环境,开发上存在不便。
本文介绍了如何在 x86 环境下,基于 Qemu 和 Docker 快速搭建 AARCH64 开发环境。

从 docker-hub 可以下载到一个名字叫 dev4arm64/aarch64:ubuntu\_19.04\_sve 的 docker image,
读者可以通过 AARCH64 开发环境准备 这一节提供的命令进入 AARCH64 开发环境。
也可以通过 附录 提供的方法,手动创建开发环境。

到目前为止,官方 release 的 gcc 还不支持 SVE intrinsics ,
但 github上 的 gcc-mirror 仓包含了一个 aarch64/sve-acle-branch 的分支,
通过 sve acle 分支的源代码,可以手动编译出一个支持 SVE intrinsics 的 gcc 编译器,
更多的信息见参考文献 [2]
本文的 AARCH64 开发环境中内置了一个手动编译的 gcc,用来支持对 SVE intrinsics 的编译。

支持 SVE intrinsics 的编译器,放在了开发环境的 /home/dev/bin/gcc_sve/ 目录下面。
下文中提到的所有测试代码、支持 SVE intrinsics 的 gcc 编译器,
都已经内置在了 dev4arm64/aarch64:ubuntu\_19.04\_sve docker image 中。本文是 AARCH64 开发系列文章的第一篇。以下假定所有代码存放于 ~/work 目录下。

AARCH64 开发环境准备

准备一台安装有 ubuntu18.04 (更高版本或者近似版本都可以) 的 x86 电脑,运行如下命令进入 AARCH64 开发环境。

sudo apt-get install qemu-user
wget "https://raw.githubusercontent.com/qemu/qemu/master/scripts/qemu-binfmt-conf.sh"
sudo chmod u+x qemu-binfmt-conf.sh
sudo ./qemu-binfmt-conf.sh --qemu-path /usr/bin
sudo docker pull dev4arm64/aarch64:ubuntu_19.04_sve                              # get docker image
sudo docker run --rm -v ~/:/mnt -it dev4arm64/aarch64:ubuntu_19.04_sve su - dev  # enter development env

以下所有内容都是在 AARCH64 开发环境中的操作,
本文的实验代码可以从参考文献 [5] 下载。

AARCH64 基本汇编编译运行

切换到目录 ~/work/aarch64_asm,有一个内置的 aarch64 的基本汇编测试程序,如下

$ cat hello.S
        .arch armv8-a
        .text
        .align  2

        .global main
        .type   main, %function
main:
        stp     x29, x30, [sp, -16]!

        adrp    x0, hello_str
        add     x0, x0, :lo12:hello_str
        bl      printf
        mov     x0, 0

        ldp     x29, x30, [sp], 16
        ret

        .section        .rodata
        .align  4
hello_str:
        .string "hello aarch64\n"

执行 makefile 文件可以得到如下结果

$ make run clean
gcc     hello.S   -o hello
./hello
hello aarch64
rm -f hello *.o

AARCH64 Neon 编译运行

Neon 的测试代码在目录 ~/work/neon 下面。

AARCH64 Neon 汇编编译运行

这是一个批量处理16个 unsigned char 类型数据做加法运算的例子,运行 make run_asm clean 结果如下

$ make run_asm clean
cc    -c -o neon_add3.o neon_add3.S
cc -g -Wall -march=armv8.2-a -O2   -c -o neon_add3_test.o neon_add3_test.c
cc   neon_add3.o neon_add3_test.o   -o neon_add3
./neon_add3
name: data
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
name: data (new)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
rm -f *.o neon_add3 neon_hello

AARCH64 Neon intrinsics 编译运行

这是一个用neon计算 1,2,3 ... 加到99 的例子,运行 make run_intrinsics clean 结果如下

$ make run_intrinsics clean
cc -g -Wall -march=armv8.2-a -O2   -c -o neon_hello.o neon_hello.c
cc   neon_hello.o   -o neon_hello
./neon_hello
sum=4950
rm -f *.o neon_add3 neon_hello

AARCH64 SVE 编译运行

SVE 的测试代码在目录 ~/work/sve 下面。

AARCH64 SVE 汇编编译运行

这是通过sve指令计算字符串长度的例子,运行 make run_asm clean 结果如下

注意: arm sve 指令是 armv8.2 开始支持的,因此 -march 后面的参数是: armv8.2-a+sve

$ make run_asm clean
cc    -c -o sve_strlen.o sve_strlen.S
/home/dev/bin/gcc_sve/bin/aarch64-linux-gnu-gcc -g -Wall -march=armv8.2-a+sve -O2 -c -o sve_strlen_test.o sve_strlen_test.c
cc   sve_strlen.o sve_strlen_test.o   -o sve_strlen
./sve_strlen
len=9 of "hello sve"
rm -f *.o sve_strlen sve_hello

因为这个例子的代码量比较少,因此贴出 source code 的源代码,更多内容,
见参考文献 [6]

$ cat sve_strlen.S
// reference: https://alastairreid.github.io/papers/sve-ieee-micro-2017.pdf
        .arch armv8.2-a+sve
        .text
        .align  2

        .global sve_strlen
        .type   sve_strlen, %function

sve_strlen:
        mov x1, x0
        ptrue p0.b
.loop:
        setffr
        ldff1b z0.b, p0/z, [x1]
        rdffr p1.b, p0/z
        cmpeq p2.b, p1/z, z0.b, #0
        brkbs p2.b, p1/z, p2.b
        incp x1, p2.b
        b.last .loop
        sub x0, x1, x0
ret

AARCH64 SVE intrinsics 编译运行

这是一个通过 sve intrinsics 做批量运算的例子,运行 make run_intrinsics clean 结果如下

$ make run_intrinsics clean
/home/dev/bin/gcc_sve/bin/aarch64-linux-gnu-gcc -g -Wall -march=armv8.2-a+sve -O2 -c -o sve_hello.o sve_hello.c
cc   sve_hello.o   -o sve_hello
./sve_hello
0.988095 0.988095 0.988095, 0.000000, 0.988095
1.488095 1.488095 1.488095, 0.500000, 0.988095
1.654762 1.654762 1.654762, 0.666667, 0.988095
1.738095 1.738095 1.738095, 0.750000, 0.988095
1.788095 1.788095 1.788095, 0.800000, 0.988095
1.821429 1.821429 1.821429, 0.833333, 0.988095
1.845238 1.845238 1.845238, 0.857143, 0.988095
1.863095 1.863095 1.863095, 0.875000, 0.988095
1.876984 1.876984 1.876984, 0.888889, 0.988095
1.888095 1.888095 1.888095, 0.900000, 0.988095
rm -f *.o sve_strlen sve_hello

附录

下载附件:ubuntu-19.04-dockerfile 和 docker-build.sh,
在命令行上输入如下命令,等待一段时间,环境就会创建成功。

./docker-build.sh

参考文献

[1] SVE in QEMU's linux-user mode

[2] 交叉编译支持SVE ACLE的gcc

[3] qemu-user-static release

[4] ARM64编译工具链下载

[5] AARCH64 sample code

[6] Alastair Reid' page

文件名 大小 下载次数 操作
docker-build.sh 251B 10 下载
ubuntu-19.04-dockerfile 969B 10 下载
推荐阅读
关注数
2444
内容数
14
介绍Arm相关的开源软件。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息