Search code examples
assemblyx86sse

How to convert an unsigned integer to floating-point in x86 (32-bit) assembly?


I need to convert both 32-bit and 64-bit unsigned integers into floating-point values in xmm registers. There are x86 instructions to convert signed integers into single and double precision floating-point values, but nothing for unsigned integers.

Bonus: How to convert float-point values in xmm registers to 32-bit and 64-bit unsigned integers?


Solution

  • Shamelessly using Janus answer as a template (after all I really like C++):

    Generate with gcc -march=native -O3 on a i7, so this is with up to and including -mavx. uint2float and vice versa are as expected, the long conversions just have a special case for numbers greater than 263-1.

    0000000000000000 <ulong2double>:
       0:   48 85 ff                test   %rdi,%rdi
       3:   78 0b                   js     10 <ulong2double+0x10>
       5:   c4 e1 fb 2a c7          vcvtsi2sd %rdi,%xmm0,%xmm0
       a:   c3                      retq   
       b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
      10:   48 89 f8                mov    %rdi,%rax
      13:   83 e7 01                and    $0x1,%edi
      16:   48 d1 e8                shr    %rax
      19:   48 09 f8                or     %rdi,%rax
      1c:   c4 e1 fb 2a c0          vcvtsi2sd %rax,%xmm0,%xmm0
      21:   c5 fb 58 c0             vaddsd %xmm0,%xmm0,%xmm0
      25:   c3                      retq   
    
    0000000000000030 <ulong2float>:
      30:   48 85 ff                test   %rdi,%rdi
      33:   78 0b                   js     40 <ulong2float+0x10>
      35:   c4 e1 fa 2a c7          vcvtsi2ss %rdi,%xmm0,%xmm0
      3a:   c3                      retq   
      3b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
      40:   48 89 f8                mov    %rdi,%rax
      43:   83 e7 01                and    $0x1,%edi
      46:   48 d1 e8                shr    %rax
      49:   48 09 f8                or     %rdi,%rax
      4c:   c4 e1 fa 2a c0          vcvtsi2ss %rax,%xmm0,%xmm0
      51:   c5 fa 58 c0             vaddss %xmm0,%xmm0,%xmm0
      55:   c3                      retq   
    
    0000000000000060 <uint2double>:
      60:   89 ff                   mov    %edi,%edi
      62:   c4 e1 fb 2a c7          vcvtsi2sd %rdi,%xmm0,%xmm0
      67:   c3                      retq   
    
    0000000000000070 <uint2float>:
      70:   89 ff                   mov    %edi,%edi
      72:   c4 e1 fa 2a c7          vcvtsi2ss %rdi,%xmm0,%xmm0
      77:   c3                      retq