unsigned int tga_convert_color(unsigned int pixel, unsigned int bpp_in,
                               unsigned char alphabits,
                               unsigned int format_out) {
  unsigned char r, g, b, a;
  switch (bpp_in) {
  case 32:
    if (alphabits == 0) {
      goto is_24_bit_in_disguise;
    }
    break;
  case 24:
  is_24_bit_in_disguise:
    pixel |= 0xFF000000;
    break;
  case 15:
  is_15_bit_in_disguise:
    r = (unsigned char)(((float)((pixel & 0x7C00) >> 10)) * 8.2258f);
    g = (unsigned char)(((float)((pixel & 0x03E0) >> 5)) * 8.2258f);
    b = (unsigned char)(((float)(pixel & 0x001F)) * 8.2258f);
    pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
    break;
  case 16:
    if (alphabits == 1) {
      goto is_15_bit_in_disguise;
    }
    r = (unsigned char)(((float)((pixel & 0xF800) >> 11)) * 8.2258f);
    g = (unsigned char)(((float)((pixel & 0x07E0) >> 5)) * 4.0476f);
    b = (unsigned char)(((float)(pixel & 0x001F)) * 8.2258f);
    pixel = 0xFF000000 + (r << 16) + (g << 8) + b;
    break;
  }
  pixel = (pixel & 0xFF00FF00) + ((pixel & 0xFF) << 16) +
          ((pixel & 0xFF0000) >> 16);
  r = pixel & 0x000000FF;
  g = (pixel & 0x0000FF00) >> 8;
  b = (pixel & 0x00FF0000) >> 16;
  a = (pixel & 0xFF000000) >> 24;
  r = (unsigned char)(((float)r / 255.0f) * ((float)a / 255.0f) * 255.0f);
  g = (unsigned char)(((float)g / 255.0f) * ((float)a / 255.0f) * 255.0f);
  b = (unsigned char)(((float)b / 255.0f) * ((float)a / 255.0f) * 255.0f);
  pixel = r + (g << 8) + (b << 16) + (a << 24);
  switch (format_out) {
  case (4):
    break;
  case (3):
    pixel &= 0x00FFFFFF;
    break;
  }
  return (pixel);
}


x86 assembly (clang, -O0):
<tga_convert_color>:
push   %rbp
mov    %rsp,%rbp
mov    %dl,%al
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %al,-0x9(%rbp)
mov    %ecx,-0x10(%rbp)
mov    -0x8(%rbp),%eax
add    $0xfffffff1,%eax
mov    %eax,%ecx
mov    %rcx,-0x20(%rbp)
sub    $0x11,%eax
ja     125f <tga_convert_color+0x15f>
mov    -0x20(%rbp),%rax
lea    0xeda(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
movzbl -0x9(%rbp),%eax
cmp    $0x0,%eax
jne    114d <tga_convert_color+0x4d>
jmp    1157 <tga_convert_color+0x57>
jmp    125f <tga_convert_color+0x15f>
jmp    1157 <tga_convert_color+0x57>
mov    -0x4(%rbp),%eax
or     $0xff000000,%eax
mov    %eax,-0x4(%rbp)
jmp    125f <tga_convert_color+0x15f>
jmp    116c <tga_convert_color+0x6c>
mov    -0x4(%rbp),%eax
shr    $0xa,%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
movss  0xe7f(%rip),%xmm1
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x11(%rbp)
mov    -0x4(%rbp),%eax
shr    $0x5,%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x12(%rbp)
mov    -0x4(%rbp),%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x13(%rbp)
movzbl -0x11(%rbp),%eax
shl    $0x10,%eax
add    $0xff000000,%eax
movzbl -0x12(%rbp),%ecx
shl    $0x8,%ecx
add    %ecx,%eax
movzbl -0x13(%rbp),%ecx
add    %ecx,%eax
mov    %eax,-0x4(%rbp)
jmp    125f <tga_convert_color+0x15f>
movzbl -0x9(%rbp),%eax
cmp    $0x1,%eax
jne    11ee <tga_convert_color+0xee>
jmp    116c <tga_convert_color+0x6c>
movzwl -0x4(%rbp),%eax
shr    $0xb,%eax
cvtsi2ss %eax,%xmm0
movss  0xdff(%rip),%xmm1
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x11(%rbp)
mov    -0x4(%rbp),%eax
shr    $0x5,%eax
and    $0x3f,%eax
cvtsi2ss %eax,%xmm0
movss  0xde3(%rip),%xmm2
mulss  %xmm2,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x12(%rbp)
mov    -0x4(%rbp),%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x13(%rbp)
movzbl -0x11(%rbp),%eax
shl    $0x10,%eax
add    $0xff000000,%eax
movzbl -0x12(%rbp),%ecx
shl    $0x8,%ecx
add    %ecx,%eax
movzbl -0x13(%rbp),%ecx
add    %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%ecx
mov    %ecx,%eax
and    $0xff00ff00,%eax
mov    %cl,%dl
movzbl %dl,%edx
shl    $0x10,%edx
or     %edx,%eax
and    $0xff0000,%ecx
shr    $0x10,%ecx
or     %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%al
mov    %al,-0x11(%rbp)
mov    -0x3(%rbp),%al
mov    %al,-0x12(%rbp)
mov    -0x2(%rbp),%al
mov    %al,-0x13(%rbp)
mov    -0x1(%rbp),%al
mov    %al,-0x14(%rbp)
movzbl -0x11(%rbp),%eax
cvtsi2ss %eax,%xmm0
movss  0xd5f(%rip),%xmm1
movss  %xmm1,-0x28(%rbp)
divss  %xmm1,%xmm0
movzbl -0x14(%rbp),%eax
cvtsi2ss %eax,%xmm2
divss  %xmm1,%xmm2
mulss  %xmm2,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x11(%rbp)
movzbl -0x12(%rbp),%eax
cvtsi2ss %eax,%xmm0
divss  %xmm1,%xmm0
movzbl -0x14(%rbp),%eax
cvtsi2ss %eax,%xmm2
divss  %xmm1,%xmm2
mulss  %xmm2,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x12(%rbp)
movzbl -0x13(%rbp),%eax
cvtsi2ss %eax,%xmm0
divss  %xmm1,%xmm0
movzbl -0x14(%rbp),%eax
cvtsi2ss %eax,%xmm2
divss  %xmm1,%xmm2
mulss  %xmm2,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %al,-0x13(%rbp)
movzbl -0x11(%rbp),%eax
movzbl -0x12(%rbp),%ecx
shl    $0x8,%ecx
or     %ecx,%eax
movzbl -0x13(%rbp),%ecx
shl    $0x10,%ecx
or     %ecx,%eax
movzbl -0x14(%rbp),%ecx
shl    $0x18,%ecx
or     %ecx,%eax
mov    %eax,-0x4(%rbp)
mov    -0x10(%rbp),%eax
mov    %eax,-0x24(%rbp)
sub    $0x3,%eax
je     1367 <tga_convert_color+0x267>
jmp    1351 <tga_convert_color+0x251>
mov    -0x24(%rbp),%eax
sub    $0x4,%eax
jne    1372 <tga_convert_color+0x272>
jmp    1362 <tga_convert_color+0x262>
jmp    1372 <tga_convert_color+0x272>
mov    -0x4(%rbp),%eax
and    $0xffffff,%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<tga_convert_color>:
add    $0xfffffff1,%esi
cmp    $0x11,%esi
ja     11b8 <tga_convert_color+0xb8>
lea    0xf1d(%rip),%rax
movslq (%rax,%rsi,4),%rsi
add    %rax,%rsi
jmp    *%rsi
cmp    $0x1,%dl
jne    1158 <tga_convert_color+0x58>
mov    %edi,%eax
shr    $0xa,%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
movss  0xecb(%rip),%xmm1
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %edi,%edx
shr    $0x5,%edx
and    $0x1f,%edx
xorps  %xmm0,%xmm0
cvtsi2ss %edx,%xmm0
mulss  %xmm1,%xmm0
jmp    118b <tga_convert_color+0x8b>
test   %dl,%dl
jne    11b8 <tga_convert_color+0xb8>
jmp    11b2 <tga_convert_color+0xb2>
mov    %edi,%eax
shr    $0xb,%eax
and    $0x1f,%eax
cvtsi2ss %eax,%xmm0
movss  0xe94(%rip),%xmm1
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%eax
mov    %edi,%edx
shr    $0x5,%edx
and    $0x3f,%edx
xorps  %xmm0,%xmm0
cvtsi2ss %edx,%xmm0
mulss  0xe79(%rip),%xmm0
cvttss2si %xmm0,%edx
and    $0x1f,%edi
xorps  %xmm0,%xmm0
cvtsi2ss %edi,%xmm0
mulss  %xmm1,%xmm0
cvttss2si %xmm0,%esi
shl    $0x10,%eax
movzbl %dl,%edx
shl    $0x8,%edx
or     %eax,%edx
movzbl %sil,%edi
or     %edx,%edi
or     $0xff000000,%edi
mov    %edi,%eax
shr    $0x10,%eax
mov    %edi,%edx
shr    $0x8,%edx
movd   %edi,%xmm0
movd   %edx,%xmm1
movzbl %al,%eax
cvtsi2ss %eax,%xmm2
punpckldq %xmm0,%xmm1
mov    %edi,%eax
shr    $0x18,%eax
movss  0xe26(%rip),%xmm0
divss  %xmm0,%xmm2
cvtsi2ss %eax,%xmm3
divss  %xmm0,%xmm3
mulss  %xmm3,%xmm2
mulss  %xmm0,%xmm2
cvttss2si %xmm2,%eax
movdqa 0xe0e(%rip),%xmm0
pand   %xmm0,%xmm1
cvtdq2ps %xmm1,%xmm1
movaps 0xe10(%rip),%xmm2
divps  %xmm2,%xmm1
shufps $0x0,%xmm3,%xmm3
mulps  %xmm1,%xmm3
mulps  %xmm2,%xmm3
cvttps2dq %xmm3,%xmm1
movzbl %al,%eax
pand   %xmm0,%xmm1
movdqa %xmm1,%xmm0
pslld  $0x10,%xmm0
pslld  $0x8,%xmm1
movd   %xmm1,%edx
or     %eax,%edx
pshufd $0x55,%xmm0,%xmm0
movd   %xmm0,%esi
or     %edx,%esi
and    $0xff000000,%edi
xor    %eax,%eax
cmp    $0x3,%ecx
cmovne %edi,%eax
or     %esi,%eax
ret

LLVM IR (-O0):
define i32 @tga_convert_color(i32 %0, i32 %1, i8 zeroext %2, i32 %3) {
%5 = alloca i32
%6 = alloca i32
%7 = alloca i8
%8 = alloca i32
%9 = alloca i8
%10 = alloca i8
%11 = alloca i8
%12 = alloca i8
store i32 %0, i32* %5
store i32 %1, i32* %6
store i8 %2, i8* %7
store i32 %3, i32* %8
%13 = load i32, i32* %6
switch i32 %13, label %88 [
i32 32, label %14
i32 24, label %20
i32 15, label %24
i32 16, label %54
]
14: ; preds = %4
%15 = load i8, i8* %7
%16 = zext i8 %15 to i32
%17 = icmp eq i32 %16, 0
br i1 %17, label %18, label %19
18: ; preds = %14
br label %21
19: ; preds = %14
br label %88
20: ; preds = %4
br label %21
21: ; preds = %20, %18
%22 = load i32, i32* %5
%23 = or i32 %22, -16777216
store i32 %23, i32* %5
br label %88
24: ; preds = %4
br label %25
25: ; preds = %58, %24
%26 = load i32, i32* %5
%27 = and i32 %26, 31744
%28 = lshr i32 %27, 10
%29 = uitofp i32 %28 to float
%30 = fmul float %29, 0x4020739C00000000
%31 = fptoui float %30 to i8
store i8 %31, i8* %9
%32 = load i32, i32* %5
%33 = and i32 %32, 992
%34 = lshr i32 %33, 5
%35 = uitofp i32 %34 to float
%36 = fmul float %35, 0x4020739C00000000
%37 = fptoui float %36 to i8
store i8 %37, i8* %10
%38 = load i32, i32* %5
%39 = and i32 %38, 31
%40 = uitofp i32 %39 to float
%41 = fmul float %40, 0x4020739C00000000
%42 = fptoui float %41 to i8
store i8 %42, i8* %11
%43 = load i8, i8* %9
%44 = zext i8 %43 to i32
%45 = shl i32 %44, 16
%46 = add i32 -16777216, %45
%47 = load i8, i8* %10
%48 = zext i8 %47 to i32
%49 = shl i32 %48, 8
%50 = add i32 %46, %49
%51 = load i8, i8* %11
%52 = zext i8 %51 to i32
%53 = add i32 %50, %52
store i32 %53, i32* %5
br label %88
54: ; preds = %4
%55 = load i8, i8* %7
%56 = zext i8 %55 to i32
%57 = icmp eq i32 %56, 1
br i1 %57, label %58, label %59
58: ; preds = %54
br label %25
59: ; preds = %54
%60 = load i32, i32* %5
%61 = and i32 %60, 63488
%62 = lshr i32 %61, 11
%63 = uitofp i32 %62 to float
%64 = fmul float %63, 0x4020739C00000000
%65 = fptoui float %64 to i8
store i8 %65, i8* %9
%66 = load i32, i32* %5
%67 = and i32 %66, 2016
%68 = lshr i32 %67, 5
%69 = uitofp i32 %68 to float
%70 = fmul float %69, 0x401030BE00000000
%71 = fptoui float %70 to i8
store i8 %71, i8* %10
%72 = load i32, i32* %5
%73 = and i32 %72, 31
%74 = uitofp i32 %73 to float
%75 = fmul float %74, 0x4020739C00000000
%76 = fptoui float %75 to i8
store i8 %76, i8* %11
%77 = load i8, i8* %9
%78 = zext i8 %77 to i32
%79 = shl i32 %78, 16
%80 = add i32 -16777216, %79
%81 = load i8, i8* %10
%82 = zext i8 %81 to i32
%83 = shl i32 %82, 8
%84 = add i32 %80, %83
%85 = load i8, i8* %11
%86 = zext i8 %85 to i32
%87 = add i32 %84, %86
store i32 %87, i32* %5
br label %88
88: ; preds = %4, %59, %25, %21, %19
%89 = load i32, i32* %5
%90 = and i32 %89, -16711936
%91 = load i32, i32* %5
%92 = and i32 %91, 255
%93 = shl i32 %92, 16
%94 = add i32 %90, %93
%95 = load i32, i32* %5
%96 = and i32 %95, 16711680
%97 = lshr i32 %96, 16
%98 = add i32 %94, %97
store i32 %98, i32* %5
%99 = load i32, i32* %5
%100 = and i32 %99, 255
%101 = trunc i32 %100 to i8
store i8 %101, i8* %9
%102 = load i32, i32* %5
%103 = and i32 %102, 65280
%104 = lshr i32 %103, 8
%105 = trunc i32 %104 to i8
store i8 %105, i8* %10
%106 = load i32, i32* %5
%107 = and i32 %106, 16711680
%108 = lshr i32 %107, 16
%109 = trunc i32 %108 to i8
store i8 %109, i8* %11
%110 = load i32, i32* %5
%111 = and i32 %110, -16777216
%112 = lshr i32 %111, 24
%113 = trunc i32 %112 to i8
store i8 %113, i8* %12
%114 = load i8, i8* %9
%115 = uitofp i8 %114 to float
%116 = fdiv float %115, 2.550000e+02
%117 = load i8, i8* %12
%118 = uitofp i8 %117 to float
%119 = fdiv float %118, 2.550000e+02
%120 = fmul float %116, %119
%121 = fmul float %120, 2.550000e+02
%122 = fptoui float %121 to i8
store i8 %122, i8* %9
%123 = load i8, i8* %10
%124 = uitofp i8 %123 to float
%125 = fdiv float %124, 2.550000e+02
%126 = load i8, i8* %12
%127 = uitofp i8 %126 to float
%128 = fdiv float %127, 2.550000e+02
%129 = fmul float %125, %128
%130 = fmul float %129, 2.550000e+02
%131 = fptoui float %130 to i8
store i8 %131, i8* %10
%132 = load i8, i8* %11
%133 = uitofp i8 %132 to float
%134 = fdiv float %133, 2.550000e+02
%135 = load i8, i8* %12
%136 = uitofp i8 %135 to float
%137 = fdiv float %136, 2.550000e+02
%138 = fmul float %134, %137
%139 = fmul float %138, 2.550000e+02
%140 = fptoui float %139 to i8
store i8 %140, i8* %11
%141 = load i8, i8* %9
%142 = zext i8 %141 to i32
%143 = load i8, i8* %10
%144 = zext i8 %143 to i32
%145 = shl i32 %144, 8
%146 = add nsw i32 %142, %145
%147 = load i8, i8* %11
%148 = zext i8 %147 to i32
%149 = shl i32 %148, 16
%150 = add nsw i32 %146, %149
%151 = load i8, i8* %12
%152 = zext i8 %151 to i32
%153 = shl i32 %152, 24
%154 = add nsw i32 %150, %153
store i32 %154, i32* %5
%155 = load i32, i32* %8
switch i32 %155, label %160 [
i32 4, label %156
i32 3, label %157
]
156: ; preds = %88
br label %160
157: ; preds = %88
%158 = load i32, i32* %5
%159 = and i32 %158, 16777215
store i32 %159, i32* %5
br label %160
160: ; preds = %88, %157, %156
%161 = load i32, i32* %5
ret i32 %161
}

LLVM IR (-O2):
define i32 @tga_convert_color(i32 %0, i32 %1, i8 zeroext %2, i32 %3) {
switch i32 %1, label %57 [
i32 32, label %5
i32 24, label %7
i32 15, label %9
i32 16, label %32
]
5: ; preds = %4
%6 = icmp eq i8 %2, 0
br i1 %6, label %7, label %57
7: ; preds = %4, %5
%8 = or i32 %0, -16777216
br label %57
9: ; preds = %32, %4
%10 = lshr i32 %0, 10
%11 = and i32 %10, 31
%12 = uitofp i32 %11 to float
%13 = fmul float %12, 0x4020739C00000000
%14 = fptoui float %13 to i8
%15 = lshr i32 %0, 5
%16 = and i32 %15, 31
%17 = uitofp i32 %16 to float
%18 = fmul float %17, 0x4020739C00000000
%19 = fptoui float %18 to i8
%20 = and i32 %0, 31
%21 = uitofp i32 %20 to float
%22 = fmul float %21, 0x4020739C00000000
%23 = fptoui float %22 to i8
%24 = zext i8 %14 to i32
%25 = shl nuw nsw i32 %24, 16
%26 = zext i8 %19 to i32
%27 = shl nuw nsw i32 %26, 8
%28 = or i32 %25, %27
%29 = zext i8 %23 to i32
%30 = or i32 %28, %29
%31 = or i32 %30, -16777216
br label %57
32: ; preds = %4
%33 = icmp eq i8 %2, 1
br i1 %33, label %9, label %34
34: ; preds = %32
%35 = lshr i32 %0, 11
%36 = and i32 %35, 31
%37 = uitofp i32 %36 to float
%38 = fmul float %37, 0x4020739C00000000
%39 = fptoui float %38 to i8
%40 = lshr i32 %0, 5
%41 = and i32 %40, 63
%42 = uitofp i32 %41 to float
%43 = fmul float %42, 0x401030BE00000000
%44 = fptoui float %43 to i8
%45 = and i32 %0, 31
%46 = uitofp i32 %45 to float
%47 = fmul float %46, 0x4020739C00000000
%48 = fptoui float %47 to i8
%49 = zext i8 %39 to i32
%50 = shl nuw nsw i32 %49, 16
%51 = zext i8 %44 to i32
%52 = shl nuw nsw i32 %51, 8
%53 = or i32 %50, %52
%54 = zext i8 %48 to i32
%55 = or i32 %53, %54
%56 = or i32 %55, -16777216
br label %57
57: ; preds = %5, %4, %34, %9, %7
%58 = phi i32 [ %0, %4 ], [ %31, %9 ], [ %56, %34 ], [ %8, %7 ], [ %0, %5 ]
%59 = lshr i32 %58, 16
%60 = trunc i32 %59 to i8
%61 = lshr i32 %58, 8
%62 = insertelement <2 x i32> poison, i32 %61, i64 0
%63 = insertelement <2 x i32> %62, i32 %58, i64 1
%64 = trunc <2 x i32> %63 to <2 x i8>
%65 = lshr i32 %58, 24
%66 = trunc i32 %65 to i8
%67 = uitofp i8 %60 to float
%68 = fdiv float %67, 2.550000e+02
%69 = uitofp i8 %66 to float
%70 = fdiv float %69, 2.550000e+02
%71 = fmul float %68, %70
%72 = fmul float %71, 2.550000e+02
%73 = fptoui float %72 to i8
%74 = uitofp <2 x i8> %64 to <2 x float>
%75 = fdiv <2 x float> %74, <float 2.550000e+02, float 2.550000e+02>
%76 = insertelement <2 x float> poison, float %70, i64 0
%77 = shufflevector <2 x float> %76, <2 x float> poison, <2 x i32> zeroinitializer
%78 = fmul <2 x float> %75, %77
%79 = fmul <2 x float> %78, <float 2.550000e+02, float 2.550000e+02>
%80 = fptoui <2 x float> %79 to <2 x i8>
%81 = zext i8 %73 to i32
%82 = zext <2 x i8> %80 to <2 x i32>
%83 = shl nuw nsw <2 x i32> %82, <i32 8, i32 16>
%84 = extractelement <2 x i32> %83, i64 0
%85 = or i32 %84, %81
%86 = extractelement <2 x i32> %83, i64 1
%87 = or i32 %85, %86
%88 = and i32 %58, -16777216
%89 = icmp eq i32 %3, 3
%90 = select i1 %89, i32 0, i32 %88
%91 = or i32 %87, %90
ret i32 %91
}