Сборка:преобразовать значение с плавающей запятой в байт со знаком
-
21-09-2019 - |
Вопрос
В настоящее время я пытаюсь написать программу для блока VFP iPhone, используя ассемблерный код ARM.VFP может выполнять вычисления с плавающей запятой, но, AFAIK, нет целочисленной арифметики.Однако он может преобразовать число с плавающей запятой в целое число со знаком (4 байта).Кроме того, согласно этой быстрой ссылке: http://www.voti.nl/hvu/arm/ARMquickref.pdfкажется, он не поддерживает никаких операций переключения
я хотел бы преобразовать 4 числа с плавающей запятой, из которых я уверен, что каждое больше -127 и меньше 127, в 4 байта со знаком.
если бы у меня были доступны операции сдвига, я мог бы преобразовать число с плавающей запятой в целое число со знаком, затем сдвинуть значение на 12 байтов влево (8 и 4 байта для следующих двух значений соответственно) и побитовое ИЛИ все четыре вместе.
однако, поскольку переключение недоступно, мне нужно найти другой способ сделать это.Кроме того, я не могу использовать целочисленную арифметику (поэтому я не могу умножить уже преобразованное целое число на 2^n, чтобы сдвинуть, но вместо этого мне приходится работать с плавающей запятой).
Кто-нибудь знает, как я могу этого добиться?
Кстати, для тех, кто знаком с архитектурой ARM - я не хочу переключаться на инструкции Thumb, потому что это делается в цикле, работающем со многими элементами, и я не хочу переключаться между инструкциями большого пальца и руки внутри этого цикла (поскольку это дорогой)
Спасибо!
редактировать:
дополнительный вопрос:как я могу нормализовать вектор с тремя элементами?
Решение
Вы хотите VFP ftosis
инструкция, которая преобразует значение FP одинарной точности в 4-байтовое целое число.Если у вас есть четыре числа с плавающей запятой в s0-s3, то после выполнения:
ftosis s0, s0
ftosis s1, s1
ftosis s2, s2
ftosis s3, s3
у вас есть четыре 4-байтовых целых числа в s0-s3, которые можно хранить в памяти последовательно с помощью fstm
.
На процессоре ARM, поддерживающем NEON, вы можете использовать vcvt.s32.f32 q0, q0
выполнить четыре преобразования с помощью одной инструкции.
Редактировать Чтобы ответить на ваш дополнительный вопрос, вот простой пример функции, которая принимает в качестве входных данных указатель на четыре числа с плавающей запятой в памяти и возвращает преобразованные значения, упакованные в один int32_t:
_floatToPackedInt:
fldmias r0, {s4-s7}
ftosizs s0, s4
ftosizs s1, s5
ftosizs s2, s6
ftosizs s3, s7
fmrrs r0, r1, {s0,s1}
fmrrs r2, r3, {s2,s3}
uxtb r0, r0
uxtb r1, r1
uxtb r2, r2
orr r0, r0, r1, lsl #8
orr r0, r0, r2, lsl #16
orr r0, r0, r3, lsl #24
bx lr
На самом деле я не приложил никаких усилий для настройки этого, потому что вы не хотели бы выполнять преобразования таким образом, если бы они были критичны к производительности;вы предпочитаете либо работать с большими массивами значений и конвейеризировать этот код так, чтобы несколько преобразований выполнялись одновременно, либо чередовать его с другими операциями, которые также выполняют полезную работу.
Вы также можете вставить ssat
перед uxtb
s, чтобы любые значения, выходящие за пределы диапазона, насыщались вместо переноса.
Также имейте в виду, что этот код будет иметь низкую производительность на ядрах ARMv7;вам определенно захочется использовать векторные операции NEON на этой платформе.