unsigned char usb_crc5(unsigned char b1, unsigned char b2) {
  unsigned char crc;
  unsigned char nextb;
  unsigned char so;
  unsigned char i;
  crc = 0x1f;
  for (i = 0; i < 8; i++) {
    nextb = b1 & 0x01;
    b1 >>= 1;
    so = crc & 0x01;
    crc >>= 1;
    if (nextb != so)
      crc ^= 0x14;
  }
  for (i = 0; i < 3; i++) {
    nextb = b2 & 0x01;
    b2 >>= 1;
    so = crc & 0x01;
    crc >>= 1;
    if (nextb != so)
      crc ^= 0x14;
  }
  crc &= 0x1f;
  crc ^= 0x1f;
  return crc;
}


x86 assembly (clang, -O0):
<usb_crc5>:
push   %rbp
mov    %rsp,%rbp
mov    %sil,%al
mov    %dil,%cl
mov    %cl,-0x1(%rbp)
mov    %al,-0x2(%rbp)
movb   $0x1f,-0x3(%rbp)
movb   $0x0,-0x6(%rbp)
movzbl -0x6(%rbp),%eax
cmp    $0x8,%eax
jge    1179 <usb_crc5+0x79>
movzbl -0x1(%rbp),%eax
and    $0x1,%eax
mov    %al,-0x4(%rbp)
movzbl -0x1(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x1(%rbp)
movzbl -0x3(%rbp),%eax
and    $0x1,%eax
mov    %al,-0x5(%rbp)
movzbl -0x3(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x3(%rbp)
movzbl -0x4(%rbp),%eax
movzbl -0x5(%rbp),%ecx
cmp    %ecx,%eax
je     1167 <usb_crc5+0x67>
movzbl -0x3(%rbp),%eax
xor    $0x14,%eax
mov    %al,-0x3(%rbp)
jmp    116c <usb_crc5+0x6c>
mov    -0x6(%rbp),%al
add    $0x1,%al
mov    %al,-0x6(%rbp)
jmp    1118 <usb_crc5+0x18>
movb   $0x0,-0x6(%rbp)
movzbl -0x6(%rbp),%eax
cmp    $0x3,%eax
jge    11de <usb_crc5+0xde>
movzbl -0x2(%rbp),%eax
and    $0x1,%eax
mov    %al,-0x4(%rbp)
movzbl -0x2(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x2(%rbp)
movzbl -0x3(%rbp),%eax
and    $0x1,%eax
mov    %al,-0x5(%rbp)
movzbl -0x3(%rbp),%eax
sar    $0x1,%eax
mov    %al,-0x3(%rbp)
movzbl -0x4(%rbp),%eax
movzbl -0x5(%rbp),%ecx
cmp    %ecx,%eax
je     11cc <usb_crc5+0xcc>
movzbl -0x3(%rbp),%eax
xor    $0x14,%eax
mov    %al,-0x3(%rbp)
jmp    11d1 <usb_crc5+0xd1>
mov    -0x6(%rbp),%al
add    $0x1,%al
mov    %al,-0x6(%rbp)
jmp    117d <usb_crc5+0x7d>
movzbl -0x3(%rbp),%eax
and    $0x1f,%eax
mov    %al,-0x3(%rbp)
movzbl -0x3(%rbp),%eax
xor    $0x1f,%eax
mov    %al,-0x3(%rbp)
movzbl -0x3(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<usb_crc5>:
xor    %eax,%eax
test   $0x1,%dil
sete   %al
lea    (%rax,%rax,2),%eax
add    $0x3,%eax
mov    %edi,%ecx
shr    $0x3,%cl
mov    %eax,%edx
xor    $0xa,%dl
test   $0x2,%dil
movzbl %dl,%edx
cmovne %eax,%edx
mov    %edx,%eax
xor    $0x14,%al
test   $0x4,%dil
movzbl %al,%eax
cmovne %edx,%eax
mov    %edi,%edx
shr    $0x4,%dl
xor    %al,%cl
shr    %al
movzbl %al,%r8d
xor    $0x14,%al
test   $0x1,%cl
movzbl %al,%eax
cmove  %r8d,%eax
mov    %edi,%ecx
shr    $0x5,%cl
xor    %al,%dl
shr    %al
movzbl %al,%r8d
xor    $0x14,%al
test   $0x1,%dl
movzbl %al,%eax
cmove  %r8d,%eax
mov    %edi,%edx
shr    $0x6,%dl
xor    %al,%cl
shr    %al
movzbl %al,%r8d
xor    $0x14,%al
test   $0x1,%cl
movzbl %al,%eax
cmove  %r8d,%eax
shr    $0x7,%dil
xor    %al,%dl
shr    %al
movzbl %al,%ecx
xor    $0x14,%al
test   $0x1,%dl
movzbl %al,%eax
cmove  %ecx,%eax
mov    %eax,%ecx
shr    %cl
and    $0x1,%al
movzbl %cl,%edx
xor    $0x14,%cl
cmp    %dil,%al
movzbl %cl,%eax
cmove  %edx,%eax
mov    %esi,%ecx
shr    %cl
mov    %eax,%edx
shr    %dl
xor    %sil,%al
movzbl %dl,%edi
xor    $0x14,%dl
test   $0x1,%al
movzbl %dl,%eax
cmove  %edi,%eax
shr    $0x2,%sil
xor    %al,%cl
shr    %al
movzbl %al,%edx
xor    $0x14,%al
test   $0x1,%cl
movzbl %al,%eax
cmove  %edx,%eax
xor    %al,%sil
shr    %al
movzbl %al,%ecx
xor    $0x14,%al
test   $0x1,%sil
movzbl %al,%eax
cmove  %ecx,%eax
not    %al
and    $0x1f,%al
ret

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

LLVM IR (-O2):
define zeroext i8 @usb_crc5(i8 zeroext %0, i8 zeroext %1) {
%3 = and i8 %0, 1
%4 = icmp eq i8 %3, 0
%5 = select i1 %4, i8 6, i8 3
%6 = and i8 %0, 2
%7 = icmp eq i8 %6, 0
%8 = lshr i8 %0, 3
%9 = xor i8 %5, 10
%10 = select i1 %7, i8 %9, i8 %5
%11 = and i8 %0, 4
%12 = icmp eq i8 %11, 0
%13 = xor i8 %10, 20
%14 = select i1 %12, i8 %13, i8 %10
%15 = lshr i8 %0, 4
%16 = lshr i8 %14, 1
%17 = xor i8 %14, %8
%18 = and i8 %17, 1
%19 = icmp eq i8 %18, 0
%20 = xor i8 %16, 20
%21 = select i1 %19, i8 %16, i8 %20
%22 = lshr i8 %0, 5
%23 = lshr i8 %21, 1
%24 = xor i8 %21, %15
%25 = and i8 %24, 1
%26 = icmp eq i8 %25, 0
%27 = xor i8 %23, 20
%28 = select i1 %26, i8 %23, i8 %27
%29 = lshr i8 %0, 6
%30 = lshr i8 %28, 1
%31 = xor i8 %28, %22
%32 = and i8 %31, 1
%33 = icmp eq i8 %32, 0
%34 = xor i8 %30, 20
%35 = select i1 %33, i8 %30, i8 %34
%36 = lshr i8 %0, 7
%37 = lshr i8 %35, 1
%38 = xor i8 %35, %29
%39 = and i8 %38, 1
%40 = icmp eq i8 %39, 0
%41 = xor i8 %37, 20
%42 = select i1 %40, i8 %37, i8 %41
%43 = lshr i8 %42, 1
%44 = and i8 %42, 1
%45 = icmp eq i8 %44, %36
%46 = xor i8 %43, 20
%47 = select i1 %45, i8 %43, i8 %46
%48 = lshr i8 %1, 1
%49 = lshr i8 %47, 1
%50 = xor i8 %47, %1
%51 = and i8 %50, 1
%52 = icmp eq i8 %51, 0
%53 = xor i8 %49, 20
%54 = select i1 %52, i8 %49, i8 %53
%55 = lshr i8 %1, 2
%56 = lshr i8 %54, 1
%57 = xor i8 %54, %48
%58 = and i8 %57, 1
%59 = icmp eq i8 %58, 0
%60 = xor i8 %56, 20
%61 = select i1 %59, i8 %56, i8 %60
%62 = lshr i8 %61, 1
%63 = xor i8 %61, %55
%64 = and i8 %63, 1
%65 = icmp eq i8 %64, 0
%66 = xor i8 %62, 20
%67 = select i1 %65, i8 %62, i8 %66
%68 = and i8 %67, 31
%69 = xor i8 %68, 31
ret i8 %69
}