"=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