void fb_memconvert(unsigned char *dest, unsigned char *src, int size) {
  int i;
  unsigned char tmpr, tmpg, tmpb;
  unsigned short s, sd;
  for (i = 0; i < size; i += 2) {
    s = src[i + 1] << 8 | src[i];
    tmpr = (s >> 11) & 0x1f;
    tmpg = (s >> 6) & 0x1f;
    tmpb = (s)&0x1f;
    sd = (tmpr) | (tmpg << 6) | (tmpb << 11);
    dest[i] = (sd >> 8) & 0xff;
    dest[i + 1] = (sd)&0xff;
  }
}


x86 assembly (clang, -O0):
<fb_memconvert>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11c8 <fb_memconvert+0xc8>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movzbl (%rax,%rcx,1),%eax
shl    $0x8,%eax
mov    -0x10(%rbp),%rcx
movslq -0x18(%rbp),%rdx
movzbl (%rcx,%rdx,1),%ecx
or     %ecx,%eax
mov    %ax,-0x1e(%rbp)
movzwl -0x1e(%rbp),%eax
sar    $0xb,%eax
and    $0x1f,%eax
mov    %al,-0x19(%rbp)
movzwl -0x1e(%rbp),%eax
sar    $0x6,%eax
and    $0x1f,%eax
mov    %al,-0x1a(%rbp)
movzwl -0x1e(%rbp),%eax
and    $0x1f,%eax
mov    %al,-0x1b(%rbp)
movzbl -0x19(%rbp),%eax
movzbl -0x1a(%rbp),%ecx
shl    $0x6,%ecx
or     %ecx,%eax
movzbl -0x1b(%rbp),%ecx
shl    $0xb,%ecx
or     %ecx,%eax
mov    %ax,-0x20(%rbp)
movzwl -0x20(%rbp),%eax
sar    $0x8,%eax
and    $0xff,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
movzwl -0x20(%rbp),%eax
and    $0xff,%eax
mov    %al,%dl
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x2,%eax
mov    %eax,-0x18(%rbp)
jmp    1116 <fb_memconvert+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<fb_memconvert>:
push   %rbx
test   %edx,%edx
jle    126f <fb_memconvert+0x16f>
mov    %edx,%r10d
lea    -0x1(%r10),%r8
cmp    $0xe,%r8
jae    111d <fb_memconvert+0x1d>
xor    %ebx,%ebx
jmp    1240 <fb_memconvert+0x140>
lea    0x1(%r10),%rcx
and    $0xfffffffffffffffe,%rcx
lea    (%rsi,%rcx,1),%rdx
cmp    %rdi,%rdx
jbe    113d <fb_memconvert+0x3d>
add    %rdi,%rcx
cmp    %rsi,%rcx
jbe    113d <fb_memconvert+0x3d>
xor    %ebx,%ebx
jmp    1240 <fb_memconvert+0x140>
shr    %r8
add    $0x1,%r8
mov    %r8,%r9
and    $0xfffffffffffffff8,%r9
lea    (%r9,%r9,1),%rbx
xor    %edx,%edx
movdqa 0xea7(%rip),%xmm0
movdqa 0xeae(%rip),%xmm8
movdqa 0xeb5(%rip),%xmm9
movdqa 0xebd(%rip),%xmm3
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movdqu (%rsi,%rdx,2),%xmm7
movdqa %xmm7,%xmm5
psrlw  $0x8,%xmm5
movdqa %xmm5,%xmm2
packuswb %xmm5,%xmm2
punpcklwd %xmm5,%xmm5
movdqa %xmm7,%xmm6
psrlq  $0x8,%xmm6
pxor   %xmm1,%xmm1
punpckhbw %xmm6,%xmm1
pslld  $0x8,%xmm5
movdqa %xmm7,%xmm6
punpckhwd %xmm6,%xmm6
pand   %xmm0,%xmm6
punpcklwd %xmm7,%xmm7
pand   %xmm0,%xmm7
psrlw  $0x3,%xmm2
pand   %xmm8,%xmm2
pand   %xmm9,%xmm5
pand   %xmm9,%xmm1
movdqa %xmm7,%xmm4
pslld  $0xb,%xmm4
por    %xmm5,%xmm4
movdqa %xmm6,%xmm5
pslld  $0xb,%xmm5
por    %xmm1,%xmm5
psrld  $0x8,%xmm4
psrld  $0x8,%xmm5
pand   %xmm0,%xmm5
pand   %xmm0,%xmm4
packuswb %xmm5,%xmm4
packuswb %xmm4,%xmm4
pand   %xmm3,%xmm6
pand   %xmm3,%xmm7
packuswb %xmm6,%xmm7
packuswb %xmm7,%xmm7
por    %xmm2,%xmm7
punpcklbw %xmm7,%xmm4
movdqu %xmm4,(%rdi,%rdx,2)
add    $0x8,%rdx
cmp    %rdx,%r9
jne    1180 <fb_memconvert+0x80>
cmp    %r9,%r8
je     126f <fb_memconvert+0x16f>
nopl   0x0(%rax,%rax,1)
movzbl 0x1(%rsi,%rbx,1),%ecx
mov    %ecx,%eax
shl    $0x8,%eax
movzbl (%rsi,%rbx,1),%edx
or     %edx,%eax
shr    $0x3,%cl
and    $0x7c0,%eax
shl    $0xb,%edx
or     %eax,%edx
mov    %dh,(%rdi,%rbx,1)
or     %cl,%al
mov    %al,0x1(%rdi,%rbx,1)
add    $0x2,%rbx
cmp    %r10,%rbx
jb     1240 <fb_memconvert+0x140>
pop    %rbx
ret

LLVM IR (-O0):
define void @fb_memconvert(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i8
%9 = alloca i8
%10 = alloca i8
%11 = alloca i16
%12 = alloca i16
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
store i32 0, i32* %7
br label %13
13: ; preds = %77, %3
%14 = load i32, i32* %7
%15 = load i32, i32* %6
%16 = icmp slt i32 %14, %15
br i1 %16, label %17, label %80
17: ; preds = %13
%18 = load i8*, i8** %5
%19 = load i32, i32* %7
%20 = add nsw i32 %19, 1
%21 = sext i32 %20 to i64
%22 = getelementptr inbounds i8, i8* %18, i64 %21
%23 = load i8, i8* %22
%24 = zext i8 %23 to i32
%25 = shl i32 %24, 8
%26 = load i8*, i8** %5
%27 = load i32, i32* %7
%28 = sext i32 %27 to i64
%29 = getelementptr inbounds i8, i8* %26, i64 %28
%30 = load i8, i8* %29
%31 = zext i8 %30 to i32
%32 = or i32 %25, %31
%33 = trunc i32 %32 to i16
store i16 %33, i16* %11
%34 = load i16, i16* %11
%35 = zext i16 %34 to i32
%36 = ashr i32 %35, 11
%37 = and i32 %36, 31
%38 = trunc i32 %37 to i8
store i8 %38, i8* %8
%39 = load i16, i16* %11
%40 = zext i16 %39 to i32
%41 = ashr i32 %40, 6
%42 = and i32 %41, 31
%43 = trunc i32 %42 to i8
store i8 %43, i8* %9
%44 = load i16, i16* %11
%45 = zext i16 %44 to i32
%46 = and i32 %45, 31
%47 = trunc i32 %46 to i8
store i8 %47, i8* %10
%48 = load i8, i8* %8
%49 = zext i8 %48 to i32
%50 = load i8, i8* %9
%51 = zext i8 %50 to i32
%52 = shl i32 %51, 6
%53 = or i32 %49, %52
%54 = load i8, i8* %10
%55 = zext i8 %54 to i32
%56 = shl i32 %55, 11
%57 = or i32 %53, %56
%58 = trunc i32 %57 to i16
store i16 %58, i16* %12
%59 = load i16, i16* %12
%60 = zext i16 %59 to i32
%61 = ashr i32 %60, 8
%62 = and i32 %61, 255
%63 = trunc i32 %62 to i8
%64 = load i8*, i8** %4
%65 = load i32, i32* %7
%66 = sext i32 %65 to i64
%67 = getelementptr inbounds i8, i8* %64, i64 %66
store i8 %63, i8* %67
%68 = load i16, i16* %12
%69 = zext i16 %68 to i32
%70 = and i32 %69, 255
%71 = trunc i32 %70 to i8
%72 = load i8*, i8** %4
%73 = load i32, i32* %7
%74 = add nsw i32 %73, 1
%75 = sext i32 %74 to i64
%76 = getelementptr inbounds i8, i8* %72, i64 %75
store i8 %71, i8* %76
br label %77
77: ; preds = %17
%78 = load i32, i32* %7
%79 = add nsw i32 %78, 2
store i32 %79, i32* %7
br label %13
80: ; preds = %13
ret void
}

LLVM IR (-O2):
define void @fb_memconvert(i8* nocapture writeonly %0, i8* nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %77
5: ; preds = %3
%6 = zext i32 %2 to i64
%7 = add nsw i64 %6, -1
%8 = lshr i64 %7, 1
%9 = add nuw i64 %8, 1
%10 = icmp ult i64 %7, 14
br i1 %10, label %52, label %11
11: ; preds = %5
%12 = add nuw nsw i64 %6, 1
%13 = and i64 %12, 8589934590
%14 = getelementptr i8, i8* %0, i64 %13
%15 = getelementptr i8, i8* %1, i64 %13
%16 = icmp ugt i8* %15, %0
%17 = icmp ugt i8* %14, %1
%18 = and i1 %16, %17
br i1 %18, label %52, label %19
19: ; preds = %11
%20 = and i64 %9, -8
%21 = shl i64 %20, 1
%22 = getelementptr inbounds i8, i8* %1, i64 -1
%23 = getelementptr inbounds i8, i8* %0, i64 -1
br label %24
24: ; preds = %24, %19
%25 = phi i64 [ 0, %19 ], [ %48, %24 ]
%26 = shl i64 %25, 1
%27 = or i64 %26, 1
%28 = getelementptr inbounds i8, i8* %22, i64 %27
%29 = bitcast i8* %28 to <16 x i8>*
%30 = load <16 x i8>, <16 x i8>* %29
%31 = shufflevector <16 x i8> %30, <16 x i8> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
%32 = shufflevector <16 x i8> %30, <16 x i8> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
%33 = zext <8 x i8> %32 to <8 x i32>
%34 = shl nuw nsw <8 x i32> %33, <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>
%35 = zext <8 x i8> %31 to <8 x i32>
%36 = or <8 x i32> %34, %35
%37 = lshr <8 x i8> %32, <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3>
%38 = and <8 x i32> %36, <i32 1984, i32 1984, i32 1984, i32 1984, i32 1984, i32 1984, i32 1984, i32 1984>
%39 = shl nuw nsw <8 x i32> %35, <i32 11, i32 11, i32 11, i32 11, i32 11, i32 11, i32 11, i32 11>
%40 = or <8 x i32> %38, %39
%41 = lshr <8 x i32> %40, <i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8, i32 8>
%42 = trunc <8 x i32> %41 to <8 x i8>
%43 = trunc <8 x i32> %38 to <8 x i8>
%44 = or <8 x i8> %37, %43
%45 = getelementptr inbounds i8, i8* %23, i64 %27
%46 = bitcast i8* %45 to <16 x i8>*
%47 = shufflevector <8 x i8> %42, <8 x i8> %44, <16 x i32> <i32 0, i32 8, i32 1, i32 9, i32 2, i32 10, i32 3, i32 11, i32 4, i32 12, i32 5, i32 13, i32 6, i32 14, i32 7, i32 15>
store <16 x i8> %47, <16 x i8>* %46
%48 = add nuw i64 %25, 8
%49 = icmp eq i64 %48, %20
br i1 %49, label %50, label %24
50: ; preds = %24
%51 = icmp eq i64 %9, %20
br i1 %51, label %77, label %52
52: ; preds = %11, %5, %50
%53 = phi i64 [ 0, %11 ], [ 0, %5 ], [ %21, %50 ]
br label %54
54: ; preds = %52, %54
%55 = phi i64 [ %75, %54 ], [ %53, %52 ]
%56 = or i64 %55, 1
%57 = getelementptr inbounds i8, i8* %1, i64 %56
%58 = load i8, i8* %57
%59 = zext i8 %58 to i32
%60 = shl nuw nsw i32 %59, 8
%61 = getelementptr inbounds i8, i8* %1, i64 %55
%62 = load i8, i8* %61
%63 = zext i8 %62 to i32
%64 = or i32 %60, %63
%65 = lshr i8 %58, 3
%66 = and i32 %64, 1984
%67 = shl nuw nsw i32 %63, 11
%68 = or i32 %66, %67
%69 = lshr i32 %68, 8
%70 = trunc i32 %69 to i8
%71 = getelementptr inbounds i8, i8* %0, i64 %55
store i8 %70, i8* %71
%72 = trunc i32 %66 to i8
%73 = or i8 %65, %72
%74 = getelementptr inbounds i8, i8* %0, i64 %56
store i8 %73, i8* %74
%75 = add nuw nsw i64 %55, 2
%76 = icmp ult i64 %75, %6
br i1 %76, label %54, label %77
77: ; preds = %54, %50, %3
ret void
}