Для STM32F7, который включает инструкции для двойных чисел с плавающей запятой, я хочу преобразовать uint64_t
в double
.
Чтобы проверить это, я использовал следующий код:
volatile static uint64_t m_testU64 = 45uLL * 0xFFFFFFFFuLL;
volatile static double m_testD;
#ifndef DO_NOT_USE_UL2D
m_testD = (double)m_testU64;
#else
double t = (double)(uint32_t)(m_testU64 >> 32u);
t *= 4294967296.0;
t += (double)(uint32_t)(m_testU64 & 0xFFFFFFFFu);
m_testD = t;
#endif
По умолчанию (если DO_NOT_USE_UL2D
не определено) компилятор (gcc или clang) вызывает функцию: __aeabi_ul2d()
, которая является сложной по количеству выполняемых инструкций.См. Код сборки здесь: https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/arm/ieee754-df.S#L537
Для моего конкретного примера требуется 20 инструкций без ввода в большинство ветвей
И если определено DO_NOT_USE_UL2D
, компилятор сгенерирует следующееассемблерный код:
movw r0, #1728 ; 0x6c0
vldr d2, [pc, #112] ; 0x303fa0
movt r0, #8192 ; 0x2000
vldr s0, [r0, #4]
ldr r1, [r0, #0]
vcvt.f64.u32 d0, s0
vldr s2, [r0]
vcvt.f64.u32 d1, s2
ldr r1, [r0, #4]
vfma.f64 d1, d0, d2
vstr d1, [r0, #8]
Код проще, и в нем всего 10 инструкций.
Итак, вот вопросы (если определено DO_NOT_USE_UL2D
):
- Является ли мой код (в C) правильным?
- Мой код медленнее, чем функция
__aeabi_ul2d()
(не очень важно, но немного любопытно)?
У меня естьчтобы сделать это, так как мне не разрешено использовать функцию из libgcc (есть очень веские причины для этого ...)
Помните, что основная цель этого вопроса не в производительности, мне действительно любопытноо реализации в libgcc, и я действительно хочу знать, если что-то не так в моем коде.