Как собрать инструкции ARM SVE с помощью GNU GAS или LLVM и запустить их на QEMU?

Я хочу поиграть с новым инструкции ARM SVE с использованием инструментов с открытым исходным кодом.

Для начала я хотел бы собрать минимальный пример, представленный по адресу: 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 или любой другой ассемблер с открытым исходным кодом.

Как только мне удастся собрать, я хочу запустить его в пользовательском режиме QEMU, так как 3.0.0 имеет SVE поддержку.


person Ciro Santilli    schedule 19.10.2018    source источник


Ответы (1)


Автоматический пример с утверждением

Ниже я описал, как этот пример был достигнут.

Сборка

aarch64-linux-gnu-as 2.30 в Ubuntu 18.04 уже достаточно нов для SVE, как видно из: https://sourceware.org/binutils/docs-2.30/as/AArch64-Extensions.html#AArch64-Extensions

В противном случае скомпилировать Binutils из исходного кода в Ubuntu 16.04 несложно, просто выполните:

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 ;-)

Затем используйте скомпилированный as и свяжите его с упакованным GCC в Ubuntu 16.04:

./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

В Ubuntu 19.04 Binutils 2.32 я также узнал и протестировал:

aarch64-linux-gnu-as -march=all

который также работает для SVE, я думаю, что буду использовать его больше в будущем, так как кажется, что он просто включает все функции за один раз, а не только SVE!

Моделирование QEMU

Процедура пошаговой отладки в QEMU объясняется по адресу: Как выполнить пошаговую сборку ARM в GDB на 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.

person Ciro Santilli    schedule 19.10.2018