unsigned short blend_channel16(unsigned short color1, unsigned short color2,
                               register unsigned a) {
  return (
      ((((((color1 >> 11) * a) + ((color2 >> 11) * (255 - a))) >> 8)) << 11) |
      (((((((color1 & 0x7E0) >> 5) * a) +
          (((color2 & 0x7E0) >> 5) * (255 - a))) >>
         8))
       << 5) |
      ((((color1 & 0x1F) * a) + ((color2 & 0x1F) * (255 - a))) >> 8));
}


x86 assembly (clang, -O0):
<blend_channel16>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %di,%cx
mov    %cx,-0x2(%rbp)
mov    %ax,-0x4(%rbp)
mov    %edx,-0x8(%rbp)
movzwl -0x2(%rbp),%eax
sar    $0xb,%eax
imul   -0x8(%rbp),%eax
movzwl -0x4(%rbp),%ecx
sar    $0xb,%ecx
mov    $0xff,%edx
sub    -0x8(%rbp),%edx
imul   %edx,%ecx
add    %ecx,%eax
shr    $0x8,%eax
shl    $0xb,%eax
movzwl -0x2(%rbp),%ecx
and    $0x7e0,%ecx
sar    $0x5,%ecx
imul   -0x8(%rbp),%ecx
movzwl -0x4(%rbp),%edx
and    $0x7e0,%edx
sar    $0x5,%edx
mov    $0xff,%esi
sub    -0x8(%rbp),%esi
imul   %esi,%edx
add    %edx,%ecx
shr    $0x8,%ecx
shl    $0x5,%ecx
or     %ecx,%eax
movzwl -0x2(%rbp),%ecx
and    $0x1f,%ecx
imul   -0x8(%rbp),%ecx
movzwl -0x4(%rbp),%edx
and    $0x1f,%edx
mov    $0xff,%esi
sub    -0x8(%rbp),%esi
imul   %esi,%edx
add    %edx,%ecx
shr    $0x8,%ecx
or     %ecx,%eax
movzwl %ax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<blend_channel16>:
mov    %edi,%r8d
shr    $0xb,%r8d
imul   %edx,%r8d
mov    %esi,%r9d
shr    $0xb,%r9d
mov    $0xff,%eax
sub    %edx,%eax
imul   %eax,%r9d
add    %r8d,%r9d
shl    $0x3,%r9d
and    $0xf800,%r9d
mov    %edi,%r8d
shr    $0x5,%r8d
and    $0x3f,%r8d
imul   %edx,%r8d
mov    %esi,%ecx
shr    $0x5,%ecx
and    $0x3f,%ecx
imul   %eax,%ecx
add    %r8d,%ecx
shr    $0x3,%ecx
and    $0xffe0,%ecx
and    $0x1f,%edi
imul   %edx,%edi
and    $0x1f,%esi
imul   %esi,%eax
add    %edi,%eax
shr    $0x8,%eax
or     %r9d,%eax
or     %ecx,%eax
ret

LLVM IR (-O0):
define zeroext i16 @blend_channel16(i16 zeroext %0, i16 zeroext %1, i32 %2) {
%4 = alloca i16
%5 = alloca i16
%6 = alloca i32
store i16 %0, i16* %4
store i16 %1, i16* %5
store i32 %2, i32* %6
%7 = load i16, i16* %4
%8 = zext i16 %7 to i32
%9 = ashr i32 %8, 11
%10 = load i32, i32* %6
%11 = mul i32 %9, %10
%12 = load i16, i16* %5
%13 = zext i16 %12 to i32
%14 = ashr i32 %13, 11
%15 = load i32, i32* %6
%16 = sub i32 255, %15
%17 = mul i32 %14, %16
%18 = add i32 %11, %17
%19 = lshr i32 %18, 8
%20 = shl i32 %19, 11
%21 = load i16, i16* %4
%22 = zext i16 %21 to i32
%23 = and i32 %22, 2016
%24 = ashr i32 %23, 5
%25 = load i32, i32* %6
%26 = mul i32 %24, %25
%27 = load i16, i16* %5
%28 = zext i16 %27 to i32
%29 = and i32 %28, 2016
%30 = ashr i32 %29, 5
%31 = load i32, i32* %6
%32 = sub i32 255, %31
%33 = mul i32 %30, %32
%34 = add i32 %26, %33
%35 = lshr i32 %34, 8
%36 = shl i32 %35, 5
%37 = or i32 %20, %36
%38 = load i16, i16* %4
%39 = zext i16 %38 to i32
%40 = and i32 %39, 31
%41 = load i32, i32* %6
%42 = mul i32 %40, %41
%43 = load i16, i16* %5
%44 = zext i16 %43 to i32
%45 = and i32 %44, 31
%46 = load i32, i32* %6
%47 = sub i32 255, %46
%48 = mul i32 %45, %47
%49 = add i32 %42, %48
%50 = lshr i32 %49, 8
%51 = or i32 %37, %50
%52 = trunc i32 %51 to i16
ret i16 %52
}

LLVM IR (-O2):
define zeroext i16 @blend_channel16(i16 zeroext %0, i16 zeroext %1, i32 %2) {
%4 = zext i16 %0 to i32
%5 = lshr i32 %4, 11
%6 = mul i32 %5, %2
%7 = zext i16 %1 to i32
%8 = lshr i32 %7, 11
%9 = sub i32 255, %2
%10 = mul i32 %8, %9
%11 = add i32 %10, %6
%12 = shl i32 %11, 3
%13 = and i32 %12, 63488
%14 = lshr i32 %4, 5
%15 = and i32 %14, 63
%16 = mul i32 %15, %2
%17 = lshr i32 %7, 5
%18 = and i32 %17, 63
%19 = mul i32 %18, %9
%20 = add i32 %19, %16
%21 = lshr i32 %20, 3
%22 = and i32 %21, 65504
%23 = and i32 %4, 31
%24 = mul i32 %23, %2
%25 = and i32 %7, 31
%26 = mul i32 %25, %9
%27 = add i32 %26, %24
%28 = lshr i32 %27, 8
%29 = or i32 %13, %28
%30 = or i32 %29, %22
%31 = trunc i32 %30 to i16
ret i16 %31
}