void shiftbitsright(unsigned char *p, unsigned long num, unsigned long by) {
  int step, off;
  unsigned char *e;
  if (by >= num) {
    for (; num > 8; p++, num -= 8)
      *p = 0;
    *p &= (~0x00) >> num;
    return;
  }
  step = by / 8;
  off = by % 8;
  for (e = p + (num + 7) / 8 - 1; e > p + step; e--)
    *e = (*(e - step) >> off) | (*(e - step - 1) << (8 - off));
  *e = *(e - step) >> off;
  for (e = p; e < p + step; e++)
    *e = 0;
}


x86 assembly (clang, -O0):
<shiftbitsright>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x18(%rbp),%rax
cmp    -0x10(%rbp),%rax
jb     116f <shiftbitsright+0x6f>
jmp    1123 <shiftbitsright+0x23>
cmpq   $0x8,-0x10(%rbp)
jbe    1152 <shiftbitsright+0x52>
mov    -0x8(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x8(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x8(%rbp)
mov    -0x10(%rbp),%rax
sub    $0x8,%rax
mov    %rax,-0x10(%rbp)
jmp    1123 <shiftbitsright+0x23>
mov    -0x10(%rbp),%rax
mov    %eax,%ecx
mov    $0xffffffff,%edx
sar    %cl,%edx
mov    -0x8(%rbp),%rax
movzbl (%rax),%ecx
and    %edx,%ecx
mov    %cl,(%rax)
jmp    125d <shiftbitsright+0x15d>
mov    -0x18(%rbp),%rax
shr    $0x3,%rax
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%rax
and    $0x7,%rax
mov    %eax,-0x20(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x10(%rbp),%rcx
add    $0x7,%rcx
shr    $0x3,%rcx
add    %rcx,%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    -0x8(%rbp),%rcx
movslq -0x1c(%rbp),%rdx
add    %rdx,%rcx
cmp    %rcx,%rax
jbe    1207 <shiftbitsright+0x107>
mov    -0x28(%rbp),%rax
movslq -0x1c(%rbp),%rdx
xor    %ecx,%ecx
sub    %rdx,%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x20(%rbp),%ecx
sar    %cl,%eax
mov    -0x28(%rbp),%rcx
movslq -0x1c(%rbp),%rsi
xor    %edx,%edx
sub    %rsi,%rdx
movzbl -0x1(%rcx,%rdx,1),%edx
mov    $0x8,%ecx
sub    -0x20(%rbp),%ecx
shl    %cl,%edx
mov    %edx,%ecx
or     %ecx,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,(%rax)
mov    -0x28(%rbp),%rax
add    $0xffffffffffffffff,%rax
mov    %rax,-0x28(%rbp)
jmp    11a0 <shiftbitsright+0xa0>
mov    -0x28(%rbp),%rax
movslq -0x1c(%rbp),%rdx
xor    %ecx,%ecx
sub    %rdx,%rcx
movzbl (%rax,%rcx,1),%eax
mov    -0x20(%rbp),%ecx
sar    %cl,%eax
mov    %al,%cl
mov    -0x28(%rbp),%rax
mov    %cl,(%rax)
mov    -0x8(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x28(%rbp),%rax
mov    -0x8(%rbp),%rcx
movslq -0x1c(%rbp),%rdx
add    %rdx,%rcx
cmp    %rcx,%rax
jae    125d <shiftbitsright+0x15d>
mov    -0x28(%rbp),%rax
movb   $0x0,(%rax)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    122d <shiftbitsright+0x12d>
pop    %rbp
ret

x86 assembly (clang, -O2):
<shiftbitsright>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
mov    %rsi,%r10
cmp    %rsi,%rdx
jae    1348 <shiftbitsright+0x238>
mov    %edx,%ecx
and    $0x7,%cl
add    $0x7,%r10
shr    $0x3,%r10
mov    %rdx,%r8
shl    $0x1d,%r8
mov    %rdx,%rax
shr    $0x3,%rax
movslq %eax,%rbx
lea    (%rdi,%rbx,1),%r9
lea    (%rdi,%r10,1),%rbp
add    $0xffffffffffffffff,%rbp
mov    %rbx,%rax
neg    %rax
cmp    %r9,%rbp
jbe    131e <shiftbitsright+0x20e>
mov    %rbx,%r11
not    %r11
add    %r10,%r11
cmp    $0x10,%r11
jb     1300 <shiftbitsright+0x1f0>
mov    %r10,%r14
sub    %rbx,%r14
lea    -0x2(%r14),%r12
mov    %rbp,%rsi
sub    %r12,%rsi
cmp    %rbp,%rsi
ja     1300 <shiftbitsright+0x1f0>
lea    (%rdi,%r11,1),%r15
mov    %r15,%rsi
sub    %r12,%rsi
cmp    %r15,%rsi
ja     1300 <shiftbitsright+0x1f0>
lea    (%rdi,%r14,1),%rsi
add    $0xfffffffffffffffe,%rsi
cmp    %rdi,%rsi
jb     1300 <shiftbitsright+0x1f0>
lea    (%rdi,%r10,1),%rsi
add    %rdi,%rbx
add    $0x1,%rbx
lea    0x1(%rdi),%r12
add    %rdi,%r14
cmp    %r14,%rbx
setb   %r14b
cmp    %rsi,%r12
setb   %r12b
cmp    %r15,%rbx
setb   %bl
cmp    %rdi,%rsi
seta   %sil
test   %r12b,%r14b
jne    1300 <shiftbitsright+0x1f0>
and    %sil,%bl
jne    1300 <shiftbitsright+0x1f0>
mov    %r11,%r14
and    $0xfffffffffffffff0,%r14
sub    %r14,%rbp
movzbl %dl,%edx
movd   %edx,%xmm0
lea    (%r10,%rdi,1),%rdx
add    $0xfffffffffffffff0,%rdx
pand   0xdf3(%rip),%xmm0
pxor   %xmm1,%xmm1
pslldq $0xf,%xmm0
psrldq $0xf,%xmm0
movdqa 0xded(%rip),%xmm2
mov    %r14,%rbx
cs nopw 0x0(%rax,%rax,1)
movdqu -0x1(%rdx,%rax,1),%xmm4
movdqu (%rdx,%rax,1),%xmm3
movdqa %xmm3,%xmm5
punpcklbw %xmm1,%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm5
punpckhbw %xmm1,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
packuswb %xmm5,%xmm3
movdqa %xmm4,%xmm5
punpcklbw %xmm1,%xmm5
pshufd $0x4e,%xmm5,%xmm5
pshuflw $0x1b,%xmm5,%xmm5
pshufhw $0x1b,%xmm5,%xmm5
punpckhbw %xmm1,%xmm4
pshufd $0x4e,%xmm4,%xmm4
pshuflw $0x1b,%xmm4,%xmm4
pshufhw $0x1b,%xmm4,%xmm4
packuswb %xmm5,%xmm4
movdqa %xmm3,%xmm5
punpckhbw %xmm4,%xmm5
psrlw  %xmm0,%xmm5
pand   %xmm2,%xmm5
punpcklbw %xmm4,%xmm3
psrlw  %xmm0,%xmm3
pand   %xmm2,%xmm3
packuswb %xmm5,%xmm3
movdqa %xmm3,%xmm4
punpcklbw %xmm1,%xmm4
pshufd $0x4e,%xmm4,%xmm4
pshuflw $0x1b,%xmm4,%xmm4
pshufhw $0x1b,%xmm4,%xmm4
punpckhbw %xmm1,%xmm3
pshufd $0x4e,%xmm3,%xmm3
pshuflw $0x1b,%xmm3,%xmm3
pshufhw $0x1b,%xmm3,%xmm3
packuswb %xmm4,%xmm3
movdqu %xmm3,(%rdx)
add    $0xfffffffffffffff0,%rdx
add    $0xfffffffffffffff0,%rbx
jne    1230 <shiftbitsright+0x120>
cmp    %r14,%r11
je     131e <shiftbitsright+0x20e>
nopl   0x0(%rax)
movzbl 0x0(%rbp,%rax,1),%edx
movzbl -0x1(%rbp,%rax,1),%esi
shl    $0x8,%esi
or     %edx,%esi
shr    %cl,%esi
mov    %sil,0x0(%rbp)
add    $0xffffffffffffffff,%rbp
cmp    %r9,%rbp
ja     1300 <shiftbitsright+0x1f0>
mov    0x0(%rbp,%rax,1),%al
shr    %cl,%al
mov    %al,0x0(%rbp)
movabs $0x100000000,%rax
cmp    %rax,%r8
jl     1364 <shiftbitsright+0x254>
lea    0x1(%rdi),%rdx
cmp    %rdx,%r9
cmova  %r9,%rdx
sub    %rdi,%rdx
xor    %esi,%esi
jmp    135f <shiftbitsright+0x24f>
cmp    $0x9,%r10
jb     1364 <shiftbitsright+0x254>
add    $0xfffffffffffffff7,%r10
shr    $0x3,%r10
add    $0x1,%r10
xor    %esi,%esi
mov    %r10,%rdx
call   1030 <memset@plt>
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define void @shiftbitsright(i8* %0, i64 %1, i64 %2) {
%4 = alloca i8*
%5 = alloca i64
%6 = alloca i64
%7 = alloca i32
%8 = alloca i32
%9 = alloca i8*
store i8* %0, i8** %4
store i64 %1, i64* %5
store i64 %2, i64* %6
%10 = load i64, i64* %6
%11 = load i64, i64* %5
%12 = icmp uge i64 %10, %11
br i1 %12, label %13, label %33
13: ; preds = %3
br label %14
14: ; preds = %19, %13
%15 = load i64, i64* %5
%16 = icmp ugt i64 %15, 8
br i1 %16, label %17, label %24
17: ; preds = %14
%18 = load i8*, i8** %4
store i8 0, i8* %18
br label %19
19: ; preds = %17
%20 = load i8*, i8** %4
%21 = getelementptr inbounds i8, i8* %20, i32 1
store i8* %21, i8** %4
%22 = load i64, i64* %5
%23 = sub i64 %22, 8
store i64 %23, i64* %5
br label %14
24: ; preds = %14
%25 = load i64, i64* %5
%26 = trunc i64 %25 to i32
%27 = ashr i32 -1, %26
%28 = load i8*, i8** %4
%29 = load i8, i8* %28
%30 = zext i8 %29 to i32
%31 = and i32 %30, %27
%32 = trunc i32 %31 to i8
store i8 %32, i8* %28
br label %105
33: ; preds = %3
%34 = load i64, i64* %6
%35 = udiv i64 %34, 8
%36 = trunc i64 %35 to i32
store i32 %36, i32* %7
%37 = load i64, i64* %6
%38 = urem i64 %37, 8
%39 = trunc i64 %38 to i32
store i32 %39, i32* %8
%40 = load i8*, i8** %4
%41 = load i64, i64* %5
%42 = add i64 %41, 7
%43 = udiv i64 %42, 8
%44 = getelementptr inbounds i8, i8* %40, i64 %43
%45 = getelementptr inbounds i8, i8* %44, i64 -1
store i8* %45, i8** %9
br label %46
46: ; preds = %77, %33
%47 = load i8*, i8** %9
%48 = load i8*, i8** %4
%49 = load i32, i32* %7
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds i8, i8* %48, i64 %50
%52 = icmp ugt i8* %47, %51
br i1 %52, label %53, label %80
53: ; preds = %46
%54 = load i8*, i8** %9
%55 = load i32, i32* %7
%56 = sext i32 %55 to i64
%57 = sub i64 0, %56
%58 = getelementptr inbounds i8, i8* %54, i64 %57
%59 = load i8, i8* %58
%60 = zext i8 %59 to i32
%61 = load i32, i32* %8
%62 = ashr i32 %60, %61
%63 = load i8*, i8** %9
%64 = load i32, i32* %7
%65 = sext i32 %64 to i64
%66 = sub i64 0, %65
%67 = getelementptr inbounds i8, i8* %63, i64 %66
%68 = getelementptr inbounds i8, i8* %67, i64 -1
%69 = load i8, i8* %68
%70 = zext i8 %69 to i32
%71 = load i32, i32* %8
%72 = sub nsw i32 8, %71
%73 = shl i32 %70, %72
%74 = or i32 %62, %73
%75 = trunc i32 %74 to i8
%76 = load i8*, i8** %9
store i8 %75, i8* %76
br label %77
77: ; preds = %53
%78 = load i8*, i8** %9
%79 = getelementptr inbounds i8, i8* %78, i32 -1
store i8* %79, i8** %9
br label %46
80: ; preds = %46
%81 = load i8*, i8** %9
%82 = load i32, i32* %7
%83 = sext i32 %82 to i64
%84 = sub i64 0, %83
%85 = getelementptr inbounds i8, i8* %81, i64 %84
%86 = load i8, i8* %85
%87 = zext i8 %86 to i32
%88 = load i32, i32* %8
%89 = ashr i32 %87, %88
%90 = trunc i32 %89 to i8
%91 = load i8*, i8** %9
store i8 %90, i8* %91
%92 = load i8*, i8** %4
store i8* %92, i8** %9
br label %93
93: ; preds = %102, %80
%94 = load i8*, i8** %9
%95 = load i8*, i8** %4
%96 = load i32, i32* %7
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds i8, i8* %95, i64 %97
%99 = icmp ult i8* %94, %98
br i1 %99, label %100, label %105
100: ; preds = %93
%101 = load i8*, i8** %9
store i8 0, i8* %101
br label %102
102: ; preds = %100
%103 = load i8*, i8** %9
%104 = getelementptr inbounds i8, i8* %103, i32 1
store i8* %104, i8** %9
br label %93
105: ; preds = %24, %93
ret void
}

LLVM IR (-O2):
define void @shiftbitsright(i8* %0, i64 %1, i64 %2) {
%4 = ptrtoint i8* %0 to i64
%5 = icmp ult i64 %2, %1
br i1 %5, label %12, label %6
6: ; preds = %3
%7 = icmp ugt i64 %1, 8
br i1 %7, label %8, label %110
8: ; preds = %6
%9 = add i64 %1, -9
%10 = lshr i64 %9, 3
%11 = add nuw nsw i64 %10, 1
br label %110
12: ; preds = %3
%13 = trunc i64 %2 to i8
%14 = and i8 %13, 7
%15 = add i64 %1, 7
%16 = lshr i64 %15, 3
%17 = getelementptr i8, i8* %0, i64 %16
%18 = shl i64 %2, 29
%19 = ashr i64 %18, 32
%20 = getelementptr inbounds i8, i8* %0, i64 %19
%21 = getelementptr i8, i8* %17, i64 -1
%22 = icmp ugt i8* %21, %20
%23 = sub nsw i64 0, %19
br i1 %22, label %24, label %99
24: ; preds = %12
%25 = xor i64 %19, -1
%26 = add nsw i64 %16, %25
%27 = icmp ult i64 %26, 16
br i1 %27, label %88, label %28
28: ; preds = %24
%29 = add nsw i64 %16, -2
%30 = sub nsw i64 %29, %19
%31 = sub i64 0, %30
%32 = getelementptr i8, i8* %21, i64 %31
%33 = icmp ugt i8* %32, %21
%34 = xor i64 %19, -1
%35 = add nsw i64 %16, %34
%36 = getelementptr i8, i8* %0, i64 %35
%37 = sub i64 0, %30
%38 = getelementptr i8, i8* %36, i64 %37
%39 = icmp ugt i8* %38, %36
%40 = getelementptr i8, i8* %0, i64 %30
%41 = icmp ult i8* %40, %0
%42 = or i1 %33, %39
%43 = or i1 %42, %41
br i1 %43, label %88, label %44
44: ; preds = %28
%45 = add nsw i64 %19, 1
%46 = getelementptr i8, i8* %0, i64 %45
%47 = getelementptr i8, i8* %0, i64 1
%48 = sub nsw i64 %16, %19
%49 = getelementptr i8, i8* %0, i64 %48
%50 = xor i64 %19, -1
%51 = add nsw i64 %16, %50
%52 = getelementptr i8, i8* %0, i64 %51
%53 = icmp ult i8* %46, %49
%54 = icmp ult i8* %47, %17
%55 = and i1 %53, %54
%56 = icmp ult i8* %46, %52
%57 = icmp ugt i8* %17, %0
%58 = and i1 %56, %57
%59 = or i1 %55, %58
br i1 %59, label %88, label %60
60: ; preds = %44
%61 = and i64 %26, -16
%62 = sub nsw i64 0, %61
%63 = getelementptr i8, i8* %21, i64 %62
%64 = insertelement <16 x i8> poison, i8 %13, i64 0
%65 = shufflevector <16 x i8> %64, <16 x i8> poison, <16 x i32> zeroinitializer
br label %66
66: ; preds = %66, %60
%67 = phi i64 [ 0, %60 ], [ %84, %66 ]
%68 = sub i64 0, %67
%69 = getelementptr i8, i8* %21, i64 %68
%70 = getelementptr inbounds i8, i8* %69, i64 %23
%71 = getelementptr inbounds i8, i8* %70, i64 -15
%72 = bitcast i8* %71 to <16 x i8>*
%73 = load <16 x i8>, <16 x i8>* %72
%74 = shufflevector <16 x i8> %73, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%75 = getelementptr inbounds i8, i8* %70, i64 -1
%76 = getelementptr inbounds i8, i8* %75, i64 -15
%77 = bitcast i8* %76 to <16 x i8>*
%78 = load <16 x i8>, <16 x i8>* %77
%79 = shufflevector <16 x i8> %78, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%80 = call <16 x i8> @llvm.fshr.v16i8(<16 x i8> %79, <16 x i8> %74, <16 x i8> %65)
%81 = shufflevector <16 x i8> %80, <16 x i8> poison, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
%82 = getelementptr i8, i8* %69, i64 -15
%83 = bitcast i8* %82 to <16 x i8>*
store <16 x i8> %81, <16 x i8>* %83
%84 = add nuw i64 %67, 16
%85 = icmp eq i64 %84, %61
br i1 %85, label %86, label %66
86: ; preds = %66
%87 = icmp eq i64 %26, %61
br i1 %87, label %99, label %88
88: ; preds = %44, %28, %24, %86
%89 = phi i8* [ %21, %44 ], [ %21, %28 ], [ %21, %24 ], [ %63, %86 ]
br label %90
90: ; preds = %88, %90
%91 = phi i8* [ %97, %90 ], [ %89, %88 ]
%92 = getelementptr inbounds i8, i8* %91, i64 %23
%93 = load i8, i8* %92
%94 = getelementptr inbounds i8, i8* %92, i64 -1
%95 = load i8, i8* %94
%96 = tail call i8 @llvm.fshr.i8(i8 %95, i8 %93, i8 %13)
store i8 %96, i8* %91
%97 = getelementptr inbounds i8, i8* %91, i64 -1
%98 = icmp ugt i8* %97, %20
br i1 %98, label %90, label %99
99: ; preds = %90, %86, %12
%100 = phi i8* [ %21, %12 ], [ %63, %86 ], [ %97, %90 ]
%101 = getelementptr inbounds i8, i8* %100, i64 %23
%102 = load i8, i8* %101
%103 = lshr i8 %102, %14
store i8 %103, i8* %100
%104 = icmp sgt i64 %18, 4294967295
br i1 %104, label %105, label %110
105: ; preds = %99
%106 = add i64 %19, %4
%107 = add i64 %4, 1
%108 = call i64 @llvm.umax.i64(i64 %106, i64 %107)
%109 = sub i64 %108, %4
br label %110
110: ; preds = %8, %105, %6, %99
ret void
}