long rnc_crc(void *data, long len) {
  unsigned short crctab[256];
  unsigned short val;
  int i, j;
  unsigned char *p = data;
  for (i = 0; i < 256; i++) {
    val = i;
    for (j = 0; j < 8; j++) {
      if (val & 1)
        val = (val >> 1) ^ 0xA001;
      else
        val = (val >> 1);
    }
    crctab[i] = val;
  }
  val = 0;
  while (len--) {
    val ^= *p++;
    val = (val >> 8) ^ crctab[val & 0xFF];
  }
  return val;
}


x86 assembly (clang, -O0):
<rnc_crc>:
push   %rbp
mov    %rsp,%rbp
sub    $0x1b0,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x228(%rbp)
movl   $0x0,-0x218(%rbp)
cmpl   $0x100,-0x218(%rbp)
jge    11de <rnc_crc+0xde>
mov    -0x218(%rbp),%eax
mov    %ax,-0x212(%rbp)
movl   $0x0,-0x21c(%rbp)
cmpl   $0x8,-0x21c(%rbp)
jge    11b4 <rnc_crc+0xb4>
movzwl -0x212(%rbp),%eax
and    $0x1,%eax
cmp    $0x0,%eax
je     118a <rnc_crc+0x8a>
movzwl -0x212(%rbp),%eax
sar    $0x1,%eax
xor    $0xa001,%eax
mov    %ax,-0x212(%rbp)
jmp    119b <rnc_crc+0x9b>
movzwl -0x212(%rbp),%eax
sar    $0x1,%eax
mov    %ax,-0x212(%rbp)
jmp    11a0 <rnc_crc+0xa0>
mov    -0x21c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x21c(%rbp)
jmp    114f <rnc_crc+0x4f>
mov    -0x212(%rbp),%cx
movslq -0x218(%rbp),%rax
mov    %cx,-0x210(%rbp,%rax,2)
ff
mov    -0x218(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x218(%rbp)
jmp    1128 <rnc_crc+0x28>
movw   $0x0,-0x212(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,%rcx
add    $0xffffffffffffffff,%rcx
mov    %rcx,-0x10(%rbp)
cmp    $0x0,%rax
je     1258 <rnc_crc+0x158>
mov    -0x228(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x228(%rbp)
movzbl (%rax),%ecx
movzwl -0x212(%rbp),%eax
xor    %ecx,%eax
mov    %ax,-0x212(%rbp)
movzwl -0x212(%rbp),%eax
sar    $0x8,%eax
movzwl -0x212(%rbp),%ecx
and    $0xff,%ecx
movslq %ecx,%rcx
movzwl -0x210(%rbp,%rcx,2),%ecx
ff
xor    %ecx,%eax
mov    %ax,-0x212(%rbp)
jmp    11e7 <rnc_crc+0xe7>
movzwl -0x212(%rbp),%eax
add    $0x1b0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<rnc_crc>:
sub    $0x188,%rsp
movdqa 0xef1(%rip),%xmm0
xor    %eax,%eax
movdqa 0xef7(%rip),%xmm1
movdqa 0xeff(%rip),%xmm2
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movdqa %xmm0,%xmm3
psrlw  $0x1,%xmm3
movdqa %xmm0,%xmm4
psllw  $0xf,%xmm4
psraw  $0xf,%xmm4
movdqa %xmm4,%xmm5
pandn  %xmm3,%xmm5
pxor   %xmm1,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
movdqa %xmm3,%xmm4
psrlw  $0x1,%xmm4
psllw  $0xf,%xmm3
psraw  $0xf,%xmm3
movdqa %xmm3,%xmm5
pandn  %xmm4,%xmm5
pxor   %xmm1,%xmm4
pand   %xmm3,%xmm4
por    %xmm5,%xmm4
movdqa %xmm4,%xmm3
psrlw  $0x1,%xmm3
psllw  $0xf,%xmm4
psraw  $0xf,%xmm4
movdqa %xmm4,%xmm5
pandn  %xmm3,%xmm5
pxor   %xmm1,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
movdqa %xmm3,%xmm4
psrlw  $0x1,%xmm4
psllw  $0xf,%xmm3
psraw  $0xf,%xmm3
movdqa %xmm3,%xmm5
pandn  %xmm4,%xmm5
pxor   %xmm1,%xmm4
pand   %xmm3,%xmm4
por    %xmm5,%xmm4
movdqa %xmm4,%xmm3
psrlw  $0x1,%xmm3
psllw  $0xf,%xmm4
psraw  $0xf,%xmm4
movdqa %xmm4,%xmm5
pandn  %xmm3,%xmm5
pxor   %xmm1,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
movdqa %xmm3,%xmm4
psrlw  $0x1,%xmm4
psllw  $0xf,%xmm3
psraw  $0xf,%xmm3
movdqa %xmm3,%xmm5
pandn  %xmm4,%xmm5
pxor   %xmm1,%xmm4
pand   %xmm3,%xmm4
por    %xmm5,%xmm4
movdqa %xmm4,%xmm3
psrlw  $0x1,%xmm3
psllw  $0xf,%xmm4
psraw  $0xf,%xmm4
movdqa %xmm4,%xmm5
pandn  %xmm3,%xmm5
pxor   %xmm1,%xmm3
pand   %xmm4,%xmm3
por    %xmm5,%xmm3
movdqa %xmm3,%xmm4
psrlw  $0x1,%xmm4
psllw  $0xf,%xmm3
psraw  $0xf,%xmm3
movdqa %xmm3,%xmm5
pandn  %xmm4,%xmm5
pxor   %xmm1,%xmm4
pand   %xmm3,%xmm4
por    %xmm5,%xmm4
movdqa %xmm4,-0x80(%rsp,%rax,2)
add    $0x8,%rax
paddw  %xmm2,%xmm0
cmp    $0x100,%rax
jne    1130 <rnc_crc+0x30>
test   %rsi,%rsi
je     1295 <rnc_crc+0x195>
cmp    $0x1,%rsi
jne    129f <rnc_crc+0x19f>
xor    %eax,%eax
jmp    12e5 <rnc_crc+0x1e5>
xor    %eax,%eax
add    $0x188,%rsp
ret
mov    %rsi,%rcx
and    $0xfffffffffffffffe,%rcx
xor    %eax,%eax
nopl   0x0(%rax,%rax,1)
movzbl (%rdi),%edx
movzwl %ax,%eax
xor    %eax,%edx
shr    $0x8,%eax
movzbl %dl,%edx
movzwl -0x80(%rsp,%rdx,2),%r8d
movzbl 0x1(%rdi),%edx
add    $0x2,%rdi
xor    %eax,%edx
xor    %r8d,%edx
mov    %r8d,%eax
shr    $0x8,%eax
movzbl %dl,%edx
xor    -0x80(%rsp,%rdx,2),%ax
add    $0xfffffffffffffffe,%rcx
jne    12b0 <rnc_crc+0x1b0>
test   $0x1,%sil
je     12fe <rnc_crc+0x1fe>
movzbl (%rdi),%ecx
movzwl %ax,%eax
xor    %eax,%ecx
shr    $0x8,%eax
movzbl %cl,%ecx
xor    -0x80(%rsp,%rcx,2),%ax
movzwl %ax,%eax
add    $0x188,%rsp
ret

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

LLVM IR (-O2):
define i64 @rnc_crc(i8* nocapture %0, i64 %1) {
%3 = alloca [256 x i16]
%4 = bitcast [256 x i16]* %3 to i8*
br label %5
5: ; preds = %5, %2
%6 = phi i64 [ 0, %2 ], [ %50, %5 ]
%7 = phi <8 x i16> [ <i16 0, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7>, %2 ], [ %51, %5 ]
%8 = and <8 x i16> %7, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%9 = icmp eq <8 x i16> %8, zeroinitializer
%10 = lshr <8 x i16> %7, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%11 = xor <8 x i16> %10, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%12 = select <8 x i1> %9, <8 x i16> %10, <8 x i16> %11
%13 = and <8 x i16> %12, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%14 = icmp eq <8 x i16> %13, zeroinitializer
%15 = lshr <8 x i16> %12, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%16 = xor <8 x i16> %15, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%17 = select <8 x i1> %14, <8 x i16> %15, <8 x i16> %16
%18 = and <8 x i16> %17, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%19 = icmp eq <8 x i16> %18, zeroinitializer
%20 = lshr <8 x i16> %17, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%21 = xor <8 x i16> %20, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%22 = select <8 x i1> %19, <8 x i16> %20, <8 x i16> %21
%23 = and <8 x i16> %22, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%24 = icmp eq <8 x i16> %23, zeroinitializer
%25 = lshr <8 x i16> %22, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%26 = xor <8 x i16> %25, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%27 = select <8 x i1> %24, <8 x i16> %25, <8 x i16> %26
%28 = and <8 x i16> %27, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%29 = icmp eq <8 x i16> %28, zeroinitializer
%30 = lshr <8 x i16> %27, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%31 = xor <8 x i16> %30, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%32 = select <8 x i1> %29, <8 x i16> %30, <8 x i16> %31
%33 = and <8 x i16> %32, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%34 = icmp eq <8 x i16> %33, zeroinitializer
%35 = lshr <8 x i16> %32, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%36 = xor <8 x i16> %35, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%37 = select <8 x i1> %34, <8 x i16> %35, <8 x i16> %36
%38 = and <8 x i16> %37, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%39 = icmp eq <8 x i16> %38, zeroinitializer
%40 = lshr <8 x i16> %37, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%41 = xor <8 x i16> %40, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%42 = select <8 x i1> %39, <8 x i16> %40, <8 x i16> %41
%43 = and <8 x i16> %42, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%44 = icmp eq <8 x i16> %43, zeroinitializer
%45 = lshr <8 x i16> %42, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
%46 = xor <8 x i16> %45, <i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575, i16 -24575>
%47 = select <8 x i1> %44, <8 x i16> %45, <8 x i16> %46
%48 = getelementptr inbounds [256 x i16], [256 x i16]* %3, i64 0, i64 %6
%49 = bitcast i16* %48 to <8 x i16>*
store <8 x i16> %47, <8 x i16>* %49
%50 = add nuw i64 %6, 8
%51 = add <8 x i16> %7, <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
%52 = icmp eq i64 %50, 256
br i1 %52, label %53, label %5
53: ; preds = %5
%54 = icmp eq i64 %1, 0
br i1 %54, label %104, label %55
55: ; preds = %53
%56 = and i64 %1, 1
%57 = icmp eq i64 %1, 1
br i1 %57, label %86, label %58
58: ; preds = %55
%59 = and i64 %1, -2
br label %60
60: ; preds = %60, %58
%61 = phi i8* [ %0, %58 ], [ %73, %60 ]
%62 = phi i16 [ 0, %58 ], [ %83, %60 ]
%63 = phi i64 [ 0, %58 ], [ %84, %60 ]
%64 = getelementptr inbounds i8, i8* %61, i64 1
%65 = load i8, i8* %61
%66 = zext i8 %65 to i16
%67 = lshr i16 %62, 8
%68 = and i16 %62, 255
%69 = xor i16 %68, %66
%70 = zext i16 %69 to i64
%71 = getelementptr inbounds [256 x i16], [256 x i16]* %3, i64 0, i64 %70
%72 = load i16, i16* %71
%73 = getelementptr inbounds i8, i8* %61, i64 2
%74 = load i8, i8* %64
%75 = zext i8 %74 to i16
%76 = lshr i16 %72, 8
%77 = and i16 %72, 255
%78 = xor i16 %77, %67
%79 = xor i16 %78, %75
%80 = zext i16 %79 to i64
%81 = getelementptr inbounds [256 x i16], [256 x i16]* %3, i64 0, i64 %80
%82 = load i16, i16* %81
%83 = xor i16 %82, %76
%84 = add i64 %63, 2
%85 = icmp eq i64 %84, %59
br i1 %85, label %86, label %60
86: ; preds = %60, %55
%87 = phi i16 [ undef, %55 ], [ %83, %60 ]
%88 = phi i8* [ %0, %55 ], [ %73, %60 ]
%89 = phi i16 [ 0, %55 ], [ %83, %60 ]
%90 = icmp eq i64 %56, 0
br i1 %90, label %101, label %91
91: ; preds = %86
%92 = load i8, i8* %88
%93 = zext i8 %92 to i16
%94 = lshr i16 %89, 8
%95 = and i16 %89, 255
%96 = xor i16 %95, %93
%97 = zext i16 %96 to i64
%98 = getelementptr inbounds [256 x i16], [256 x i16]* %3, i64 0, i64 %97
%99 = load i16, i16* %98
%100 = xor i16 %99, %94
br label %101
101: ; preds = %86, %91
%102 = phi i16 [ %87, %86 ], [ %100, %91 ]
%103 = zext i16 %102 to i64
br label %104
104: ; preds = %101, %53
%105 = phi i64 [ 0, %53 ], [ %103, %101 ]
ret i64 %105
}