Встроенный ассемблер gcc arm% e0 и модификаторы% f0 для 16-байтовых операндов NEON?
283 просмотра
1 ответ
Найден следующий встроенный ассемблер code
для вычисления векторного перекрестного произведения:
float32x4_t cross_test( const float32x4_t& lhs, const float32x4_t& rhs )
{
float32x4_t result;
asm volatile(
"vext.8 d6, %e2, %f2, #4 \n\t"
"vext.8 d7, %e1, %f1, #4 \n\t"
"vmul.f32 %e0, %f1, %e2 \n\t"
"vmul.f32 %f0, %e1, d6 \n\t"
"vmls.f32 %e0, %f2, %e1 \n\t"
"vmls.f32 %f0, %e2, d7 \n\t"
"vext.8 %e0, %f0, %e0, #4 "
: "+w" ( result )
: "w" ( lhs ), "w" ( rhs )
: "d6", "d7" );
return result;
}
Что означают модификаторы e
и f
после '%'
(например %e2
)? Я не могу найти ссылку на это.
Это код ассемблера, сгенерированный gcc:
vext.8 d6, d20, d21, #4
vext.8 d7, d18, d19, #4
vmul.f32 d16, d19, d20
vmul.f32 d17, d18, d6
vmls.f32 d16, d21, d18
vmls.f32 d17, d20, d7
vext.8 d16, d17, d16, #4
Теперь я понял значение используемых модификаторов. Теперь я попытался следовать алгоритму кросс-произведения. Для этого я добавил несколько дополнительных комментариев к коду ассемблера, но результат не соответствует моим ожиданиям:
// History:
// - '%e' = lower register part
// - '%f' = higher register part
// - '%?0' = res = [ x2 y2 | z2 v2 ]
// - '%?1' = lhs = [ x0 y0 | z0 v0 ]
// - '%?2' = rhs = [ x1 y1 | z1 v1 ]
// - '%e0' = [ x2 y2 ]
// - '%f0' = [ z2 v2 ]
// - '%e1' = [ x0 y0 ]
// - '%f1' = [ z0 v0 ]
// - '%e2' = [ x1 y1 ]
// - '%f2' = [ z1 v1 ]
// Implemented algorithm:
// |x2| |y0 * z1 - z0 * y1|
// |y2| = |z0 * x1 - x0 * z1|
// |z2| |x0 * y1 - y0 * x1|
asm (
"vext.8 d6, %e2, %f2, #4 \n\t" // e2=[ x1 y1 ], f2=[ z1 v1 ] -> d6=[ v1 x1 ]
"vext.8 d7, %e1, %f1, #4 \n\t" // e1=[ x0 y0 ], f1=[ z0 v0 ] -> d7=[ v0 x0 ]
"vmul.f32 %e0, %f1, %e2 \n\t" // f1=[ z0 v0 ], e2=[ x1 y1 ] -> e0=[ z0 * x1, v0 * y1 ]
"vmul.f32 %f0, %e1, d6 \n\t" // e1=[ x0 y0 ], d6=[ v1 x1 ] -> f0=[ x0 * v1, y0 * x1 ]
"vmls.f32 %e0, %f2, %e1 \n\t" // f2=[ z1 v1 ], e1=[ x0 y0 ] -> e0=[ z0 * x1 - z1 * x0, v0 * y1 - v1 * y0 ] = [ y2, - ]
"vmls.f32 %f0, %e2, d7 \n\t" // e2=[ x1 y1 ], d7=[ v0 x0 ] -> f0=[ x0 * v1 - x1 * v0, y0 * x1 - y1 * x0 ] = [ -, - ]
"vext.8 %e0, %f0, %e0, #4 " //
: "+w" ( result ) // Output section: 'w'='VFP floating point register', '+'='read/write'
: "w" ( lhs ), "w" ( rhs ) // Input section : 'w'='VFP floating point register'
: "d6", "d7" ); // Temporary 64[bit] register.
Автор: Mark
Источник
Размещён: 31.07.2019 07:57
Ответы (1)
3 плюса
Во-первых, это странно. result
не инициализируется перед оператором asm, но используется как операнд ввода / вывода с "+w" ( result )
. Я думаю "=w" (result)
, будет лучше. Это также не имеет смысла, что это volatile
; выход является чистой функцией входных данных без каких-либо побочных эффектов или зависимости от каких-либо «скрытых» входных данных, поэтому одни и те же входные данные будут давать одинаковый результат каждый раз. Таким образом, опущение volatile
позволит компилятору выполнить CSE и вывести его из циклов, если это возможно, вместо того, чтобы заставлять его пересчитывать каждый раз, когда источник запускает его с одними и теми же входами.
Я не мог найти никакой ссылки либо; Страница расширенного ASM руководства gcc содержит только модификаторы операнда для x86 , а не ARM.
Но я думаю, что мы можем увидеть модификаторы операндов, посмотрев на вывод asm:
%e0
замещен d16
, %f0
замещен d17
. %e1
есть d18
и %f1
есть d19
. %2
находится в d20
иd21
Ваши входы представляют собой 16-байтовые векторы NEON в q
регистрах. В ARM32 верхняя и нижняя половина каждого q
регистра доступны отдельно как d
регистр. (В отличие от AArch64, где каждый регистр s / d является нижним элементом различных регистров q.) Похоже, что этот код использует это преимущество для свободного тасования, используя 64-битную SIMD на старшей и младшей паре float
s, после делать 4-байтовое vext
перемешивание, чтобы смешать эти пары поплавков.
%e[operand]
нижний d
регистр операнда, %f[operand]
верхний d
регистр. Они не задокументированы, но исходный код gcc говорит ( arm_print_operand
в gcc/config/arm/arm.c#L22486
:
Эти два кода печатают регистр нижнего / верхнего двойного слова регистра неоновых квадраторов соответственно. Для типов с парной структурой можно также печатать регистры с четырьмя словами низкого / высокого слов.
Я не проверял, что произойдет, если вы примените эти модификаторы к 64-битным операндам, как это float32x2_t
, и это только я, обратный инжиниринг из одного примера. Но вполне логично, что для этого найдутся модификаторы.
Модификаторы x86 включают один для младших и старших 8 битов целочисленных регистров (так что вы можете получить AL / AH, если ваш вход как в EAX), так что вещи с частичным регистром - это определенно то, что могут делать встроенные модификаторы операнда asm GNU C.
Остерегайтесь, что недокументированные средства не поддерживаются .
Автор: Peter Cordes Размещён: 23.07.2018 03:19Вопросы из категории :
- gcc Почему порядок, в котором связаны библиотеки, иногда вызывает ошибки в GCC?
- gcc How to get rid of `deprecated conversion from string constant to ‘char*’` warnings in GCC?
- gcc How to automatically generate a stacktrace when my program crashes
- gcc Генерация зависимостей GCC для другого выходного каталога
- gcc Как имитировать ошибки выделения памяти
- arm Looking for an efficient integer square root algorithm for ARM Thumb2
- arm Как инструкции отличаются от данных?
- arm выравнивание памяти в структурах gcc
- arm Как использовать инструкцию MOV в ARM с непосредственным номером в качестве второго операнда
- arm Симулятор ARM в Windows
- inline-assembly В чем разница между «asm», «__asm» и «__asm__»?
- inline-assembly Как написать многострочный встроенный ассемблерный код в GCC C ++?
- inline-assembly Сборка x86: инструкция INC и DEC и флаг переполнения
- inline-assembly Как указать отдельный регистр в качестве ограничения в встроенной сборке ARM GCC?
- inline-assembly Написание оболочки для системных вызовов Linux int 80h в встроенной сборке GNU C
- neon ffmpeg для Android: неоновая сборка имеет перемещение текста
- neon ARM/neon memcpy optimized for *uncached* memory?
- neon Как помешать GCC взломать мою природу NEON?
- neon переупорядочение значений в 128-битном векторе в коде сборки arm neon
- neon Доступ к половине регистра в расширенной SIMD AArch64