#include <stdint.h>
/**
* Конвертация 8 элементов int16_t -> 8 элементов float.
* Требуется массив из 8 float (32 байта) на выходе.
*/
void s16_to_float_neon(const int16_t* src, float* dst) {
asm volatile (
"ld1 {v0.8h}, [%[in]] \n\t" // Загружаем 8x s16
"sxtl v1.4s, v0.4h \n\t" // Расширяем младшие 4 до s32
"sxtl2 v2.4s, v0.8h \n\t" // Расширяем старшие 4 до s32
"scvtf v1.4s, v1.4s \n\t" // Конвертируем младшие s32 -> float
"scvtf v2.4s, v2.4s \n\t" // Конвертируем старшие s32 -> float
"st1 {v1.4s, v2.4s}, [%[out]] \n\t" // Сохраняем 8 float (2 регистра)
:
: [in] "r" (src), [out] "r" (dst)
: "v0", "v1", "v2", "memory"
);
}
/**
* Конвертация 8 элементов float -> 8 элементов int16_t.
* Использует округление к ближайшему и насыщение.
*/
void float_to_s16_neon(const float* src, int16_t* dst) {
asm volatile (
"ld1 {v1.4s, v2.4s}, [%[in]] \n\t" // Загружаем 8 float
"fcvtns v1.4s, v1.4s \n\t" // Округляем float -> s32 (Low)
"fcvtns v2.4s, v2.4s \n\t" // Округляем float -> s32 (High)
"sqxtn v0.4h, v1.4s \n\t" // Сужаем s32 -> s16 с насыщением (Low)
"sqxtn2 v0.8h, v2.4s \n\t" // Сужаем s32 -> s16 с насыщением (High)
"st1 {v0.8h}, [%[out]] \n\t" // Сохраняем 8x s16
:
: [in] "r" (src), [out] "r" (dst)
: "v0", "v1", "v2", "memory"
);
}