ARMv8 выходная сборка с плавающей точкой - PullRequest
0 голосов
/ 28 декабря 2018

Для добавления двух целых чисел я пишу:

int sum;
asm volatile("add %0, x3, x4" : "=r"(sum) : :);

Как я могу сделать это с двумя числами?Я попытался:

float sum;
asm volatile("fadd %0, s3, s4" : "=r"(sum) : :);

Но выдает ошибку:

Ошибка: операнд 1 должен быть векторным регистром SIMD - `fadd x0, s3, s4 '

Есть идеи?

Ответы [ 3 ]

0 голосов
/ 04 января 2019

Поскольку регистры могут иметь несколько имен в AArch64 (v0, b0, h0, s0, d0 все ссылаются на один и тот же регистр), необходимо добавить модификатор вывода к строке печати:

На Годболте

float foo()
{
    float sum;
    asm volatile("fadd %s0, s3, s4" : "=w"(sum) : :);
    return sum;
}

double dsum()
{
    double sum;
    asm volatile("fadd %d0, d3, d4" : "=w"(sum) : :);
    return sum;
}

Произведет:

foo:
        fadd s0, s3, s4 // sum
        ret     
dsum:
        fadd d0, d3, d4 // sum
        ret  
0 голосов
/ 27 февраля 2019

ARMv7 double: %P модификатор

Разработчики GCC сообщили мне правильный недокументированный модификатор для удвоений ARMv7 в https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89482#c4 Может быть, я должен прекратить быть ленивым и grep GCC некоторыедень:

main.c

#include <assert.h>

int main(void) {
    double my_double = 1.5;
    __asm__ (
        "vmov.f64 d0, 1.0;"
        "vadd.f64 %P[my_double], %P[my_double], d0;"
        : [my_double] "+w" (my_double)
        :
        : "d0"
    );
    assert(my_double == 2.5);
}

Компиляция и запуск:

sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-gcc -O3 -std=c99 -ggdb3 -march=armv7-a -marm \
  -pedantic -Wall -Wextra -o main.out main.c
qemu-arm -L /usr/arm-linux-gnueabihf main.out

Разборка содержит:

   0x00010320 <+4>:     08 7b b7 ee     vmov.f64        d7, #120        ; 0x3fc00000  1.5
   0x00010324 <+8>:     00 0b b7 ee     vmov.f64        d0, #112        ; 0x3f800000  1.0
   0x00010328 <+12>:    00 7b 37 ee     vadd.f64        d7, d7, d0

Протестировано в Ubuntu 16.04,GCC 5.4.0, QEMU 2.5.0.

Точка определения исходного кода

0 голосов
/ 30 декабря 2018

"=r" - ограничение для целочисленных регистров GP.

Руководство GCC утверждает, что "=w" - ограничение для регистра FP / SIMD в AArch64. Но если вы попробуете это, вы получите v0, а не s0, который не будет собираться. Я не знаю обходного пути здесь, вы, вероятно, должны сообщить о gcc bugzilla, что ограничение задокументировано вруководство не работает для скалярного FP.

На Godbolt Я попробовал этот источник:

float foo()
{
    float sum;
#ifdef __aarch64__
    asm volatile("fadd %0, s3, s4" : "=w"(sum) : :);   // AArch64
#else
    asm volatile("fadds %0, s3, s4" : "=t"(sum) : :);  // ARM32
#endif
    return sum;
}

double dsum()
{
    double sum;
#ifdef __aarch64__
    asm volatile("fadd %0, d3, d4" : "=w"(sum) : :);   // AArch64
#else
    asm volatile("faddd %0, d3, d4" : "=w"(sum) : :);  // ARM32
#endif
    return sum;
}

clang7.0 (со встроенным ассемблером) требуетАСМ, чтобы быть действительным.Но для gcc мы только компилируем в asm, а у Godbolt нет «двоичного режима» для не x86.

# AArch64 gcc 8.2  -xc -O3 -fverbose-asm -Wall
# INVALID ASM, errors if you try to actually assemble it.
foo:
    fadd v0, s3, s4 // sum
    ret     
dsum:
    fadd v0, d3, d4 // sum
    ret

clang выдает тот же asm, и его встроенные ассемблерные ошибки с:

<source>:5:18: error: invalid operand for instruction
    asm volatile("fadd %0, s3, s4" : "=w"(sum) : :);
                 ^
<inline asm>:1:11: note: instantiated into assembly here
        fadd v0, s3, s4
             ^

На 32-битном ARM , =t" для одиночных работ, но "=w" для (что в руководстве сказано, что вы должны использовать для двойной точности)также дает вам s0 с GCC.Это работает с Clang, хотя.Вы должны использовать -mfloat-abi=hard и -mcpu= что-то с FPU, например, -mcpu=cortex-a15

# clang7.0 -xc -O3 -Wall--target=arm -mcpu=cortex-a15 -mfloat-abi=hard
# valid asm for ARM 32
foo:
        vadd.f32        s0, s3, s4
        bx      lr
dsum:
        vadd.f64        d0, d3, d4
        bx      lr

Но gcc не работает:

# ARM gcc 8.2  -xc -O3 -fverbose-asm -Wall -mfloat-abi=hard -mcpu=cortex-a15
foo:
        fadds s0, s3, s4        @ sum
        bx      lr  @
dsum:
        faddd s0, d3, d4        @ sum    @@@ INVALID
        bx      lr  @

Так что вы можете использовать =tдля сингла просто отлично с gcc, но для double, вероятно, вам нужен модификатор %something0, чтобы печатать имя регистра как d0 вместо s0, с выводом "=w".


Очевидно, что эти операторы asm были бы полезны только для изучения синтаксиса, если вы добавите ограничения, чтобы также указать входные операнды вместо чтения того, что произошло в s3 и s4.

См. Также https://stackoverflow.com/tags/inline-assembly/info

...