Это сложно. Нет ни одной инструкции, которая может это сделать, и наилучшее решение зависит от того, находятся ли ваши данные в памяти или они уже есть в регистрах.
Для преобразования вам нужно как минимум две операции. Сначала поворот вектора, который переставляет ваши аргументы следующим образом:
a = a1 a2
b = b1 b2
vtrn.32 a, b
a = a1 b1
b = a2 b2
А затем вы должны поменять местами аргументы каждой операции. Либо путем обращения каждого вектора в отдельности, либо путем обработки двух векторов как четырехугольного вектора и выполнения длинного обратного хода.
temp = {a, b}
temp = a1 b1 a2 b2
vrev64.32 temp, temp
temp = b1 a1 b2 a2 <-- this is what you want.
Если вы загружаете свои данные из памяти, вы можете пропустить первую инструкцию vtrn.32, потому что NEON может сделать это, пока она загружает данные, используя инструкцию vld2.32. Вот небольшая функция ассемблера, которая делает именно это:
.globl asmtest
asmtest:
vld2.32 {d0-d1}, [r0] # load two vectors and transose
vrev64.32 q0, q0 # reverse within d0 and d1
vst1.32 {d0-d1}, [r0] # store result
mov pc, lr # return from subroutine..
Кстати, небольшое примечание: инструкции vtrn.32, vzip.32 и vuzp.32 идентичны (но только если вы работаете с 32-битными сущностями)
А с присущим НЕОНУ свойством? Ну, просто сказал, что ты облажался. Как вы уже узнали, вы не можете напрямую приводить из одного типа в другой, и вы не можете напрямую смешивать четырехугольные и двойные векторы.
Это лучшее, что я придумал, используя встроенные функции (он не использует трюк vld2.32 для удобства чтения):
int main (int argc, char **args)
{
const float32_t data[4] =
{
1, 2, 3, 4
};
float32_t output[4];
/* load test vectors */
float32x2_t a = vld1_f32 (data + 0);
float32x2_t b = vld1_f32 (data + 2);
/* transpose and convert to float32x4_t */
float32x2x2_t temp = vzip_f32 (b,a);
float32x4_t result = vcombine_f32 (temp.val[0], temp.val[1]);
/* store for printing */
vst1q_f32 (output, result);
/* print out the original and transposed result */
printf ("%f %f %f %f\n", data[0], data[1], data[2], data[3]);
printf ("%f %f %f %f\n", output[0], output[1], output[2], output[3]);
}
Если вы используете GCC, это будет работать, но код, сгенерированный GCC, будет ужасным и медленным. Собственная поддержка NEON еще очень молода. Вы, вероятно, получите лучшую производительность с простым C-кодом здесь ..