ARM NEON Assembler - использование и понимание - PullRequest
2 голосов
/ 16 февраля 2012

Я новичок в ассемблере и НЕОН программировании. Моя задача - преобразовать часть алгоритма из C в ARM Assembler, используя инструкции NEON. Алгоритм принимает массив int32, загружает различные значения из этого массива, выполняет сдвиг битов и Xor и записывает результат в другой массив. Позже я буду использовать массив с 64-битными значениями, но сейчас я просто пытаюсь переписать код.

C Pseudo code:

out_array[index] = shiftSome( in_array[index] ) ^ shiftSome( in_array[index] );

Итак, вот мои вопросы относительно NEON Инструкции:

1.) Если я загружаю регистр как этот:

vld1.32 d0, [r1]

будет ли он загружать только 32 бита из памяти или 2x32 бита для заполнения 64-битного неонового D-регистра?

2.) Как я могу получить доступ к 2/4/8 (i32, i16, i8) частям D-регистра?

3.) Я пытаюсь загрузить различные значения из массива со смещением, но это не так похоже на работу ... что я делаю не так ... вот мой код: (это целочисленный массив, поэтому я пытаюсь загрузить, например, 3-элемент, который должен иметь смещение 64 бит = 8 байт)

asm volatile(
"vld1.32 d0, [%0], #8 \n"     
"vst1.32 d0, [%1]" : : "r" (a), "r" (out): "d0", "r5");

где «a» - массив, а «out» - указатель на целое число (для отладки).

4.) После загрузки значения из массива мне нужно сместить его вправо, но, похоже, оно не работает:

vshr.u32 d0, d0, #24     // C code:   x >> 24;

5.) Можно ли загрузить только 1 байт в неоновый регистр, чтобы мне не приходилось сдвигать / маскировать что-то, чтобы получить только один байт, который мне нужен?

6.) Мне нужно использовать встроенный ассемблер, но я не уверен, для чего нужна последняя строка:

input list : output list : what is this for?

7.) Знаете ли вы какие-нибудь хорошие NEON ссылки с примерами кода?

Программа должна работать на процессоре Samsung Galaxy S2, процессор Cortex-A9, если это имеет значение. Спасибо за помощь.

---------------- редактировать -------------------

Вот что я узнал:

  1. Он всегда будет загружать полный регистр (64 бит)
  2. Вы можете использовать инструкцию "vmov" для переноса части неонового регистра в регистр охраны.
  3. Смещение должно быть в регистре рук и будет добавлено к базовый адрес после доступа к памяти.
  4. Это «забитый регистр». Каждый Регистр, который используется и ни в списке ввода, ни в выводе, здесь не должно быть написано.

Ответы [ 2 ]

10 голосов
/ 17 февраля 2012

Я могу ответить на большинство ваших вопросов: (обновление: уточненный вопрос «переулка»)

1) Инструкции NEON могут загружать и хранить только целые регистры (64-битные, 128-битные) одновременно в и из памяти. Существует вариант инструкции MOV, позволяющий перемещать отдельные «дорожки» в регистры ARM или из них.

2) Вы можете использовать инструкцию NEON MOV, чтобы воздействовать на отдельные полосы. Производительность пострадает при выполнении слишком большого количества операций с одним элементом. Инструкции NEON повышают производительность приложения, выполняя параллельные операции над векторами (группами с плавающей запятой / целыми числами).

3) Непосредственные смещения значений в языке ассемблера ARM - это байты, а не элементы / регистры. Инструкции NEON допускают пост-приращение с регистром, а не с немедленным значением. Для обычных инструкций ARM ваш постинкремент 8 добавит 8 (байт) к указателю источника.

4) Сдвиги в NEON влияют на все элементы вектора. Сдвиг вправо на 24 бита с использованием vshr.u32 сместит оба 32-битных длинных без знака на 24 бита и отбросит биты, которые сдвинуты.

5) Инструкции NEON позволяют перемещать отдельные элементы в и из обычных регистров ARM, но не допускают загрузки или сохранения из памяти непосредственно в «дорожки».

6)?

7) Начните здесь: http://blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/ На сайте ARM есть хорошее руководство по NEON.

0 голосов
/ 25 декабря 2013

6) Зубчатые регистры.

asm(code : output operand list : input operand list : clobber list);

Если вы используете регистры, которые не были переданы как операнды, вам необходимо сообщить об этом компилятору.Следующий код установит значение, кратное четырем.Он использует r3 как пустой регистр и позволяет компилятору узнать об этом, указав r3 в списке clobber.Кроме того, флаги состояния процессора изменяются инструкцией ands.Добавление псевдорегистра cc в список clobber также сообщит компилятору об этой модификации.

asm (
"ands R3, %1, #3"
"eor %0, %0, r3"
: "=r"(len)
: "0"(len)
: "cc", "r3"
);
...