long double unpack_ieee754(unsigned long long int i, unsigned int bits,
                           unsigned int expbits) {
  long double result;
  long long shift;
  unsigned int bias;
  unsigned int significandbits = bits - expbits - 1;
  if (i == 0) {
    return 0.0;
  }
  result = (i & ((1LL << significandbits) - 1));
  result /= (1LL << significandbits);
  result += 1.0F;
  bias = (1 << (expbits - 1)) - 1;
  shift = ((i >> significandbits) & ((1LL << expbits) - 1)) - bias;
  while (shift > 0) {
    result *= 2.0;
    shift--;
  }
  while (shift < 0) {
    result /= 2.0;
    shift++;
  }
  result *= ((i >> (bits - 1)) & 1) ? -1.0 : 1.0;
  return result;
}


x86 assembly (clang, -O0):
<unpack_ieee754>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x18(%rbp)
mov    %esi,-0x1c(%rbp)
mov    %edx,-0x20(%rbp)
mov    -0x1c(%rbp),%eax
sub    -0x20(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x40(%rbp)
cmpq   $0x0,-0x18(%rbp)
jne    112f <unpack_ieee754+0x2f>
fldz
fstpt  -0x10(%rbp)
jmp    1246 <unpack_ieee754+0x146>
mov    -0x18(%rbp),%rax
mov    %rax,-0x58(%rbp)
mov    -0x40(%rbp),%cl
mov    $0x1,%eax
mov    %rax,%rdx
shl    %cl,%rdx
mov    -0x58(%rbp),%rcx
add    $0xffffffffffffffff,%rdx
and    %rdx,%rcx
mov    %rcx,-0x50(%rbp)
sets   %cl
movzbl %cl,%ecx
mov    %ecx,%edx
fildll -0x50(%rbp)
lea    0xe9a(%rip),%rcx
flds   (%rcx,%rdx,4)
faddp  %st,%st(1)
fstpt  -0x30(%rbp)
mov    -0x40(%rbp),%cl
shl    %cl,%rax
mov    %rax,-0x48(%rbp)
fildll -0x48(%rbp)
fldt   -0x30(%rbp)
fdivp  %st,%st(1)
fstpt  -0x30(%rbp)
fldt   -0x30(%rbp)
fld1
faddp  %st,%st(1)
fstpt  -0x30(%rbp)
mov    -0x20(%rbp),%ecx
sub    $0x1,%ecx
mov    $0x1,%eax
shl    %cl,%eax
sub    $0x1,%eax
mov    %eax,-0x3c(%rbp)
mov    -0x18(%rbp),%rax
mov    -0x40(%rbp),%ecx
shr    %cl,%rax
mov    -0x20(%rbp),%ecx
mov    $0x1,%edx
shl    %cl,%rdx
mov    %rdx,%rcx
sub    $0x1,%rcx
and    %rcx,%rax
mov    -0x3c(%rbp),%ecx
sub    %rcx,%rax
mov    %rax,-0x38(%rbp)
cmpq   $0x0,-0x38(%rbp)
jle    11ed <unpack_ieee754+0xed>
fldt   -0x30(%rbp)
fadd   %st,%st(0)
fstpt  -0x30(%rbp)
mov    -0x38(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x38(%rbp)
jmp    11c9 <unpack_ieee754+0xc9>
jmp    11f2 <unpack_ieee754+0xf2>
cmpq   $0x0,-0x38(%rbp)
jge    121c <unpack_ieee754+0x11c>
fldt   -0x30(%rbp)
flds   0xe12(%rip)
fdivrp %st,%st(1)
fstpt  -0x30(%rbp)
mov    -0x38(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x38(%rbp)
jmp    11f2 <unpack_ieee754+0xf2>
mov    -0x18(%rbp),%rax
mov    -0x1c(%rbp),%cl
add    $0xff,%cl
shr    %cl,%rax
and    $0x1,%eax
mov    %eax,%ecx
lea    0xdd3(%rip),%rax
fldl   (%rax,%rcx,8)
fldt   -0x30(%rbp)
fmulp  %st,%st(1)
fstpt  -0x30(%rbp)
fldt   -0x30(%rbp)
fstpt  -0x10(%rbp)
fldt   -0x10(%rbp)
pop    %rbp
ret

x86 assembly (clang, -O2):
<unpack_ieee754>:
fldz
test   %rdi,%rdi
je     1242 <unpack_ieee754+0x142>
fstp   %st(0)
mov    %edx,%r9d
not    %r9d
add    %esi,%r9d
mov    $0x1,%eax
mov    %r9d,%ecx
shl    %cl,%rax
lea    -0x1(%rax),%rcx
xor    %r8d,%r8d
and    %rdi,%rcx
mov    %rcx,-0x8(%rsp)
sets   %r8b
fildll -0x8(%rsp)
lea    0xec1(%rip),%rcx
fadds  (%rcx,%r8,4)
mov    %rax,-0x10(%rsp)
fildll -0x10(%rsp)
fdivrp %st,%st(1)
fld1
faddp  %st,%st(1)
lea    -0x1(%rdx),%ecx
mov    $0xffffffff,%r8d
shl    %cl,%r8d
not    %r8d
mov    %rdi,%r10
mov    %r9d,%ecx
shr    %cl,%r10
mov    $0xffffffffffffffff,%rax
mov    %edx,%ecx
shl    %cl,%rax
not    %rax
and    %r10,%rax
mov    %rax,%rcx
sub    %r8,%rcx
test   %rcx,%rcx
jle    11b6 <unpack_ieee754+0xb6>
sub    %r8,%rax
add    $0x1,%rax
fldz
fldz
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
fstp   %st(1)
fstp   %st(0)
fadd   %st,%st(0)
add    $0xffffffffffffffff,%rax
cmp    $0x1,%rax
fldz
fldz
ja     11a0 <unpack_ieee754+0xa0>
jmp    122a <unpack_ieee754+0x12a>
js     11be <unpack_ieee754+0xbe>
fldz
fldz
jmp    122a <unpack_ieee754+0x12a>
mov    %r8d,%r9d
sub    %eax,%r9d
not    %rax
add    %r8,%rax
fldz
and    $0x7,%r9
je     11f8 <unpack_ieee754+0xf8>
fstp   %st(0)
neg    %r9
xor    %edx,%edx
nopl   0x0(%rax)
fmuls  0xe22(%rip)
add    $0xffffffffffffffff,%rdx
cmp    %rdx,%r9
jne    11e0 <unpack_ieee754+0xe0>
sub    %rdx,%rcx
fld    %st(0)
fxch   %st(1)
jmp    11f8 <unpack_ieee754+0xf8>
cmp    $0x7,%rax
fldz
fxch   %st(1)
fxch   %st(2)
jb     122a <unpack_ieee754+0x12a>
fstp   %st(2)
fstp   %st(0)
flds   0xdfa(%rip)
fldz
fstp   %st(0)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
fmul   %st,%st(1)
add    $0x8,%rcx
fldz
jne    1210 <unpack_ieee754+0x110>
fstp   %st(1)
fstp   %st(0)
add    $0xff,%sil
movzbl %sil,%eax
bt     %rax,%rdi
fld    %st(0)
fchs
fcmovnb %st(1),%st
fstp   %st(1)
ret

LLVM IR (-O0):
define x86_fp80 @unpack_ieee754(i64 %0, i32 %1, i32 %2) {
%4 = alloca x86_fp80
%5 = alloca i64
%6 = alloca i32
%7 = alloca i32
%8 = alloca x86_fp80
%9 = alloca i64
%10 = alloca i32
%11 = alloca i32
store i64 %0, i64* %5
store i32 %1, i32* %6
store i32 %2, i32* %7
%12 = load i32, i32* %6
%13 = load i32, i32* %7
%14 = sub i32 %12, %13
%15 = sub i32 %14, 1
store i32 %15, i32* %11
%16 = load i64, i64* %5
%17 = icmp eq i64 %16, 0
br i1 %17, label %18, label %19
18: ; preds = %3
store x86_fp80 0xK00000000000000000000, x86_fp80* %4
br label %82
19: ; preds = %3
%20 = load i64, i64* %5
%21 = load i32, i32* %11
%22 = zext i32 %21 to i64
%23 = shl i64 1, %22
%24 = sub nsw i64 %23, 1
%25 = and i64 %20, %24
%26 = uitofp i64 %25 to x86_fp80
store x86_fp80 %26, x86_fp80* %8
%27 = load i32, i32* %11
%28 = zext i32 %27 to i64
%29 = shl i64 1, %28
%30 = sitofp i64 %29 to x86_fp80
%31 = load x86_fp80, x86_fp80* %8
%32 = fdiv x86_fp80 %31, %30
store x86_fp80 %32, x86_fp80* %8
%33 = load x86_fp80, x86_fp80* %8
%34 = fadd x86_fp80 %33, 0xK3FFF8000000000000000
store x86_fp80 %34, x86_fp80* %8
%35 = load i32, i32* %7
%36 = sub i32 %35, 1
%37 = shl i32 1, %36
%38 = sub nsw i32 %37, 1
store i32 %38, i32* %10
%39 = load i64, i64* %5
%40 = load i32, i32* %11
%41 = zext i32 %40 to i64
%42 = lshr i64 %39, %41
%43 = load i32, i32* %7
%44 = zext i32 %43 to i64
%45 = shl i64 1, %44
%46 = sub nsw i64 %45, 1
%47 = and i64 %42, %46
%48 = load i32, i32* %10
%49 = zext i32 %48 to i64
%50 = sub i64 %47, %49
store i64 %50, i64* %9
br label %51
51: ; preds = %54, %19
%52 = load i64, i64* %9
%53 = icmp sgt i64 %52, 0
br i1 %53, label %54, label %59
54: ; preds = %51
%55 = load x86_fp80, x86_fp80* %8
%56 = fmul x86_fp80 %55, 0xK40008000000000000000
store x86_fp80 %56, x86_fp80* %8
%57 = load i64, i64* %9
%58 = add nsw i64 %57, -1
store i64 %58, i64* %9
br label %51
59: ; preds = %51
br label %60
60: ; preds = %63, %59
%61 = load i64, i64* %9
%62 = icmp slt i64 %61, 0
br i1 %62, label %63, label %68
63: ; preds = %60
%64 = load x86_fp80, x86_fp80* %8
%65 = fdiv x86_fp80 %64, 0xK40008000000000000000
store x86_fp80 %65, x86_fp80* %8
%66 = load i64, i64* %9
%67 = add nsw i64 %66, 1
store i64 %67, i64* %9
br label %60
68: ; preds = %60
%69 = load i64, i64* %5
%70 = load i32, i32* %6
%71 = sub i32 %70, 1
%72 = zext i32 %71 to i64
%73 = lshr i64 %69, %72
%74 = and i64 %73, 1
%75 = icmp ne i64 %74, 0
%76 = zext i1 %75 to i64
%77 = select i1 %75, double -1.000000e+00, double 1.000000e+00
%78 = fpext double %77 to x86_fp80
%79 = load x86_fp80, x86_fp80* %8
%80 = fmul x86_fp80 %79, %78
store x86_fp80 %80, x86_fp80* %8
%81 = load x86_fp80, x86_fp80* %8
store x86_fp80 %81, x86_fp80* %4
br label %82
82: ; preds = %68, %18
%83 = load x86_fp80, x86_fp80* %4
ret x86_fp80 %83
}

LLVM IR (-O2):
define x86_fp80 @unpack_ieee754(i64 %0, i32 %1, i32 %2) {
%4 = icmp eq i64 %0, 0
br i1 %4, label %76, label %5
5: ; preds = %3
%6 = xor i32 %2, -1
%7 = add i32 %6, %1
%8 = zext i32 %7 to i64
%9 = shl nuw i64 1, %8
%10 = add nsw i64 %9, -1
%11 = and i64 %10, %0
%12 = uitofp i64 %11 to x86_fp80
%13 = sitofp i64 %9 to x86_fp80
%14 = fdiv x86_fp80 %12, %13
%15 = fadd x86_fp80 %14, 0xK3FFF8000000000000000
%16 = add i32 %2, -1
%17 = shl nsw i32 -1, %16
%18 = xor i32 %17, -1
%19 = lshr i64 %0, %8
%20 = zext i32 %2 to i64
%21 = shl nsw i64 -1, %20
%22 = xor i64 %21, -1
%23 = and i64 %19, %22
%24 = zext i32 %18 to i64
%25 = sub i64 %23, %24
%26 = icmp sgt i64 %25, 0
br i1 %26, label %48, label %27
27: ; preds = %5
%28 = icmp slt i64 %25, 0
br i1 %28, label %29, label %67
29: ; preds = %27
%30 = sub i64 %24, %23
%31 = xor i64 %23, -1
%32 = add i64 %31, %24
%33 = and i64 %30, 7
%34 = icmp eq i64 %33, 0
br i1 %34, label %43, label %35
35: ; preds = %29, %35
%36 = phi x86_fp80 [ %39, %35 ], [ %15, %29 ]
%37 = phi i64 [ %40, %35 ], [ %25, %29 ]
%38 = phi i64 [ %41, %35 ], [ 0, %29 ]
%39 = fmul x86_fp80 %36, 0xK3FFE8000000000000000
%40 = add i64 %37, 1
%41 = add i64 %38, 1
%42 = icmp eq i64 %41, %33
br i1 %42, label %43, label %35
43: ; preds = %35, %29
%44 = phi x86_fp80 [ undef, %29 ], [ %39, %35 ]
%45 = phi x86_fp80 [ %15, %29 ], [ %39, %35 ]
%46 = phi i64 [ %25, %29 ], [ %40, %35 ]
%47 = icmp ult i64 %32, 7
br i1 %47, label %67, label %54
48: ; preds = %5, %48
%49 = phi x86_fp80 [ %51, %48 ], [ %15, %5 ]
%50 = phi i64 [ %52, %48 ], [ %25, %5 ]
%51 = fmul x86_fp80 %49, 0xK40008000000000000000
%52 = add nsw i64 %50, -1
%53 = icmp ugt i64 %50, 1
br i1 %53, label %48, label %67
54: ; preds = %43, %54
%55 = phi x86_fp80 [ %64, %54 ], [ %45, %43 ]
%56 = phi i64 [ %65, %54 ], [ %46, %43 ]
%57 = fmul x86_fp80 %55, 0xK3FFE8000000000000000
%58 = fmul x86_fp80 %57, 0xK3FFE8000000000000000
%59 = fmul x86_fp80 %58, 0xK3FFE8000000000000000
%60 = fmul x86_fp80 %59, 0xK3FFE8000000000000000
%61 = fmul x86_fp80 %60, 0xK3FFE8000000000000000
%62 = fmul x86_fp80 %61, 0xK3FFE8000000000000000
%63 = fmul x86_fp80 %62, 0xK3FFE8000000000000000
%64 = fmul x86_fp80 %63, 0xK3FFE8000000000000000
%65 = add i64 %56, 8
%66 = icmp eq i64 %65, 0
br i1 %66, label %67, label %54
67: ; preds = %43, %54, %48, %27
%68 = phi x86_fp80 [ %15, %27 ], [ %51, %48 ], [ %44, %43 ], [ %64, %54 ]
%69 = add i32 %1, -1
%70 = zext i32 %69 to i64
%71 = shl nuw i64 1, %70
%72 = and i64 %71, %0
%73 = icmp eq i64 %72, 0
%74 = fneg x86_fp80 %68
%75 = select i1 %73, x86_fp80 %68, x86_fp80 %74
br label %76
76: ; preds = %3, %67
%77 = phi x86_fp80 [ %75, %67 ], [ 0xK00000000000000000000, %3 ]
ret x86_fp80 %77
}