void TexConv_AI88_ARGB4444(unsigned char *_src, unsigned char *_dst, int width,
                           int height) {
  int _size = (width * height) << 1;
  asm volatile("0: \n"
               "mov (%[_src]), %%eax     \n"
               "add $4, %[_src]          \n"
               "mov %%eax, %%edx       \n"
               "and $0xF000F000, %%eax \n"
               "mov %%eax, %%ecx       \n"
               "and $0x00F000F0, %%edx \n"
               "shl $4, %%edx          \n"
               "or %%edx, %%ecx        \n"
               "shr $4, %%edx          \n"
               "or %%edx, %%ecx        \n"
               "shr $4, %%edx          \n"
               "or %%edx, %%ecx        \n"
               "mov %%ecx, (%[_dst])     \n"
               "add $4, %[_dst]          \n"
               "decl %[_size]            \n"
               "jnz 0b \n"
               : [_src] "+S"(_src), [_dst] "+D"(_dst), [_size] "+g"(_size)
               :
               : "memory", "cc", "eax", "edx", "ecx");
}


x86 assembly (clang, -O0):
<TexConv_AI88_ARGB4444>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
mov    %ecx,-0x18(%rbp)
mov    -0x14(%rbp),%eax
imul   -0x18(%rbp),%eax
shl    $0x1,%eax
mov    %eax,-0x1c(%rbp)
mov    -0x8(%rbp),%rsi
mov    -0x10(%rbp),%rdi
mov    -0x1c(%rbp),%r8d
mov    (%rsi),%eax
add    $0x4,%rsi
mov    %eax,%edx
and    $0xf000f000,%eax
mov    %eax,%ecx
and    $0xf000f0,%edx
shl    $0x4,%edx
or     %edx,%ecx
shr    $0x4,%edx
or     %edx,%ecx
shr    $0x4,%edx
or     %edx,%ecx
mov    %ecx,(%rdi)
add    $0x4,%rdi
dec    %r8d
jne    112b <TexConv_AI88_ARGB4444+0x2b>
mov    %r8d,-0x20(%rbp)
mov    -0x20(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    %rsi,-0x8(%rbp)
mov    %rdi,-0x10(%rbp)
pop    %rbp
ret

x86 assembly (clang, -O2):
<TexConv_AI88_ARGB4444>:
mov    %edx,%r8d
mov    %rdi,%rax
imul   %ecx,%r8d
add    %r8d,%r8d
mov    %r8d,-0x4(%rsp)
mov    %rsi,%rdi
mov    %rax,%rsi
mov    (%rsi),%eax
add    $0x4,%rsi
mov    %eax,%edx
and    $0xf000f000,%eax
mov    %eax,%ecx
and    $0xf000f0,%edx
shl    $0x4,%edx
or     %edx,%ecx
shr    $0x4,%edx
or     %edx,%ecx
shr    $0x4,%edx
or     %edx,%ecx
mov    %ecx,(%rdi)
add    $0x4,%rdi
dec    %r8d
jne    1118 <TexConv_AI88_ARGB4444+0x18>
ret

LLVM IR (-O0):
define void @TexConv_AI88_ARGB4444(i8* %0, i8* %1, i32 %2, i32 %3) {
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
store i8* %0, i8** %5
store i8* %1, i8** %6
store i32 %2, i32* %7
store i32 %3, i32* %8
%10 = load i32, i32* %7
%11 = load i32, i32* %8
%12 = mul nsw i32 %10, %11
%13 = shl i32 %12, 1
store i32 %13, i32* %9
%14 = load i8*, i8** %5
%15 = load i8*, i8** %6
%16 = load i32, i32* %9
%17 = call { i8*, i8* } asm sideeffect "0: \0Amov ($0), %eax \0Aadd $$4, $0 \0Amov %eax, %edx \0Aand $$0xF000F000, %eax \0Amov %eax, %ecx \0Aand $$0x00F000F0, %edx \0Ashl $$4, %edx \0Aor %edx, %ecx \0Ashr $$4, %edx \0Aor %edx, %ecx \0Ashr $$4, %edx \0Aor %edx, %ecx \0Amov %ecx, ($1) \0Aadd $$4, $1 \0Adecl $2 \0Ajnz 0b \0A", "={si},={di},=*imr,0,1,2,~{memory},~{cc},~{eax},~{edx},~{ecx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %9, i8* %14, i8* %15, i32 %16)
%18 = extractvalue { i8*, i8* } %17, 0
%19 = extractvalue { i8*, i8* } %17, 1
store i8* %18, i8** %5
store i8* %19, i8** %6
ret void
}

LLVM IR (-O2):
define void @TexConv_AI88_ARGB4444(i8* %0, i8* %1, i32 %2, i32 %3) {
%5 = alloca i32
%6 = bitcast i32* %5 to i8*
%7 = shl i32 %2, 1
%8 = mul i32 %7, %3
store i32 %8, i32* %5
%9 = call { i8*, i8* } asm sideeffect "0: \0Amov ($0), %eax \0Aadd $$4, $0 \0Amov %eax, %edx \0Aand $$0xF000F000, %eax \0Amov %eax, %ecx \0Aand $$0x00F000F0, %edx \0Ashl $$4, %edx \0Aor %edx, %ecx \0Ashr $$4, %edx \0Aor %edx, %ecx \0Ashr $$4, %edx \0Aor %edx, %ecx \0Amov %ecx, ($1) \0Aadd $$4, $1 \0Adecl $2 \0Ajnz 0b \0A", "={si},={di},=*imr,0,1,2,~{memory},~{cc},~{eax},~{edx},~{ecx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %5, i8* %0, i8* %1, i32 %8)
ret void
}