SSE: conversion uint32 to float

Author: Wojciech Muła
Added on:2008-06-18

There is no such instruction — CVTDQ2PS converts signed 32-bit ints. Solution: first zero the MSB, such number is never negative in U2, so mentioned instruction could be used. Then add 232 if the MSB was set.

float    CONST[4]     SIMD_ALIGN = packed_float((float)((uint32_t)(1 << 31))); /* 2^31 */
uint32_t MASK_0_30[4] SIMD_ALIGN = packed_dword(0x7fffffff);
uint32_t MASK_31[4]   SIMD_ALIGN = packed_dword(0x80000000);

void convert_uint32_float(uint32_t in[4], float out[4]) {
    __asm__ volatile (
    "movdqu   (%%eax), %%xmm0  \n"
    "movdqa    %%xmm0, %%xmm1  \n"

    "pand   MASK_0_30, %%xmm0  \n" // xmm0 - mask MSB bit - never less then zero in U2
    "cvtdq2ps  %%xmm0, %%xmm0  \n" // convert this value to float

    "psrad        $32, %%xmm1  \n" // populate MSB in higher word (enough to mask CONST)
    "pand       CONST, %%xmm1  \n" // xmm1 = MSB set ? float(2^31) : float(0)

    "addps     %%xmm1, %%xmm0  \n" // add 2^31 if MSB set

    "movdqu    %%xmm0, (%%ebx) \n"

    : /* no output */
    : "a" (in),
      "b" (out)
    );
}

See a sample implementation.