unsigned short blend_multiply16(unsigned short color1, unsigned short color2) {
  return ((((((color1 >> 11)) * ((color2 >> 11)) / (0x1F))) << 11) |
          ((((((color1 & 0x7E0) >> 5)) * (((color2 & 0x7E0) >> 5)) / (0x3F)))
           << 5) |
          (((color1 & 0x1F)) * ((color2 & 0x1F)) / (0x1F)));
}


x86 assembly (clang, -O0):
<blend_multiply16>:
push   %rbp
mov    %rsp,%rbp
mov    %si,%ax
mov    %di,%cx
mov    %cx,-0x2(%rbp)
mov    %ax,-0x4(%rbp)
movzwl -0x2(%rbp),%eax
sar    $0xb,%eax
movzwl -0x4(%rbp),%ecx
sar    $0xb,%ecx
imul   %ecx,%eax
mov    $0x1f,%ecx
cltd
idiv   %ecx
shl    $0xb,%eax
mov    %eax,-0xc(%rbp)
movzwl -0x2(%rbp),%eax
and    $0x7e0,%eax
sar    $0x5,%eax
movzwl -0x4(%rbp),%ecx
and    $0x7e0,%ecx
sar    $0x5,%ecx
imul   %ecx,%eax
mov    $0x3f,%ecx
cltd
idiv   %ecx
mov    %eax,%ecx
mov    -0xc(%rbp),%eax
shl    $0x5,%ecx
or     %ecx,%eax
mov    %eax,-0x8(%rbp)
movzwl -0x2(%rbp),%eax
and    $0x1f,%eax
movzwl -0x4(%rbp),%ecx
and    $0x1f,%ecx
imul   %ecx,%eax
mov    $0x1f,%ecx
cltd
idiv   %ecx
mov    %eax,%ecx
mov    -0x8(%rbp),%eax
or     %ecx,%eax
movzwl %ax,%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<blend_multiply16>:
mov    %edi,%eax
shr    $0xb,%eax
mov    %esi,%ecx
shr    $0xb,%ecx
imul   %eax,%ecx
imul   $0x843,%ecx,%eax
shr    $0x10,%eax
sub    %eax,%ecx
movzwl %cx,%ecx
shr    %ecx
add    %eax,%ecx
and    $0xfffffff0,%ecx
shl    $0x7,%ecx
mov    %edi,%eax
shr    $0x5,%eax
and    $0x3f,%eax
mov    %esi,%edx
shr    $0x5,%edx
and    $0x3f,%edx
imul   %eax,%edx
imul   $0x411,%edx,%eax
shr    $0x10,%eax
sub    %eax,%edx
movzwl %dx,%edx
shr    %edx
add    %eax,%edx
and    $0xffffffe0,%edx
and    $0x1f,%edi
and    $0x1f,%esi
imul   %edi,%esi
imul   $0x843,%esi,%edi
shr    $0x10,%edi
sub    %edi,%esi
movzwl %si,%eax
shr    %eax
add    %edi,%eax
shr    $0x4,%eax
or     %ecx,%eax
or     %edx,%eax
ret

LLVM IR (-O0):
define zeroext i16 @blend_multiply16(i16 zeroext %0, i16 zeroext %1) {
%3 = alloca i16
%4 = alloca i16
store i16 %0, i16* %3
store i16 %1, i16* %4
%5 = load i16, i16* %3
%6 = zext i16 %5 to i32
%7 = ashr i32 %6, 11
%8 = load i16, i16* %4
%9 = zext i16 %8 to i32
%10 = ashr i32 %9, 11
%11 = mul nsw i32 %7, %10
%12 = sdiv i32 %11, 31
%13 = shl i32 %12, 11
%14 = load i16, i16* %3
%15 = zext i16 %14 to i32
%16 = and i32 %15, 2016
%17 = ashr i32 %16, 5
%18 = load i16, i16* %4
%19 = zext i16 %18 to i32
%20 = and i32 %19, 2016
%21 = ashr i32 %20, 5
%22 = mul nsw i32 %17, %21
%23 = sdiv i32 %22, 63
%24 = shl i32 %23, 5
%25 = or i32 %13, %24
%26 = load i16, i16* %3
%27 = zext i16 %26 to i32
%28 = and i32 %27, 31
%29 = load i16, i16* %4
%30 = zext i16 %29 to i32
%31 = and i32 %30, 31
%32 = mul nsw i32 %28, %31
%33 = sdiv i32 %32, 31
%34 = or i32 %25, %33
%35 = trunc i32 %34 to i16
ret i16 %35
}

LLVM IR (-O2):
define zeroext i16 @blend_multiply16(i16 zeroext %0, i16 zeroext %1) {
%3 = lshr i16 %0, 11
%4 = lshr i16 %1, 11
%5 = mul nuw nsw i16 %4, %3
%6 = udiv i16 %5, 31
%7 = shl nuw i16 %6, 11
%8 = lshr i16 %0, 5
%9 = and i16 %8, 63
%10 = lshr i16 %1, 5
%11 = and i16 %10, 63
%12 = mul nuw nsw i16 %11, %9
%13 = udiv i16 %12, 63
%14 = shl nuw nsw i16 %13, 5
%15 = and i16 %0, 31
%16 = and i16 %1, 31
%17 = mul nuw nsw i16 %16, %15
%18 = udiv i16 %17, 31
%19 = or i16 %7, %18
%20 = or i16 %19, %14
ret i16 %20
}