Это конкретно связано с Неоном ARM кодирование SIMD. Я использую Неон ARM instrinsics для определенного модуля в видеодекодере. У меня есть векторизованные данные следующим образом:
Существует четыре элемента на 32 бита в Неоновом регистре - говорят, Q0 - который имеет размер 128 битов.
3B 3A 1B 1A
Существуют еще четыре, элементы на 32 бита в другом Неоновом регистре говорят, что Q1, который имеет размер 128 битов.
3D 3C 1D 1C
Я хочу, чтобы заключительные данные были в порядке как показано ниже:
1D 1C 1B 1A
3D 3C 3B 3A
Какой Неон instrinsics может достигнуть желаемого порядка данных?
как насчет чего-то вроде этого:
int32x4_t q0, q1;
/* split into 64 bit vectors */
int32x2_t q0_hi = vget_high_s32 (q0);
int32x2_t q1_hi = vget_high_s32 (q1);
int32x2_t q0_lo = vget_low_s32 (q0);
int32x2_t q1_lo = vget_low_s32 (q1);
/* recombine into 128 bit vectors */
q0 = vcombine_s32 (q0_lo, q1_lo);
q1 = vcombine_s32 (q0_hi, q1_hi);
Теоретически это должно скомпилироваться всего в две инструкции перемещения, потому что vget_high и vget_low просто переинтерпретируют 128-битные регистры Q как два 64-битных D-регистра. vcombine otoh просто компилируется в один или два хода (зависит от распределения регистров).
Да, и порядок целых чисел в выводе мог быть совершенно неправильным. Если это так, просто замените аргументы на vcombine_s32.
Похоже, вы сможете использовать инструкцию VTRN
(например, vtrnq_u32
) для этого.
Помните, что каждый регистр q состоит из двух регистров d, например, младшая часть q0 - это d0, а старшая часть - d1. Фактически, эта операция просто меняет местами d0 и d3 (или d1 и d2, это не совсем понятно из вашего представления данных). Есть даже инструкция по свопу, чтобы сделать это в одной инструкции!
Отказ от ответственности: я не знаю встроенных функций Neon (я кодирую непосредственно на ассемблере), хотя я был бы удивлен, если бы это нельзя было сделать с помощью встроенных функций.