#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int uint16_t;

/* Variables and functions */
int ata_get_word(unsigned char const *, int);
uint16_t ata_get_bits(const unsigned char *buf, int word, int start_bit,
                      int end_bit) {
  uint16_t val = ata_get_word(buf, word);
  uint16_t shift = start_bit;
  uint16_t mask = 0;
  switch (end_bit - start_bit + 1) {
  case 1:
    mask = 1;
    break;
  case 2:
    mask = 3;
    break;
  case 3:
    mask = 7;
    break;
  case 4:
    mask = 0xF;
    break;
  case 5:
    mask = 0x1F;
    break;
  case 6:
    mask = 0x3F;
    break;
  case 7:
    mask = 0x7F;
    break;
  case 8:
    mask = 0xFF;
    break;
  case 9:
    mask = 0x1FF;
    break;
  case 10:
    mask = 0x3FF;
    break;
  case 11:
    mask = 0x7FF;
    break;
  case 12:
    mask = 0xFFF;
    break;
  case 13:
    mask = 0x1FFF;
    break;
  case 14:
    mask = 0x3FFF;
    break;
  case 15:
    mask = 0x7FFF;
    break;
  case 16:
    mask = 0xFFFF;
    break;
  }
  return (val >> shift) & mask;
}


x86 assembly (clang, -O0):
<ata_get_bits>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    %edx,-0x10(%rbp)
mov    %ecx,-0x14(%rbp)
mov    -0x8(%rbp),%rdi
mov    -0xc(%rbp),%esi
call   1030 <ata_get_word@plt>
mov    %eax,-0x18(%rbp)
mov    -0x10(%rbp),%eax
mov    %eax,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
mov    -0x14(%rbp),%eax
mov    -0x10(%rbp),%ecx
sub    %ecx,%eax
mov    %eax,%ecx
mov    %rcx,-0x28(%rbp)
sub    $0xf,%eax
ja     1227 <ata_get_bits+0x117>
mov    -0x28(%rbp),%rax
lea    0xe9d(%rip),%rcx
movslq (%rcx,%rax,4),%rax
add    %rcx,%rax
jmp    *%rax
movl   $0x1,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x3,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x7,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0xf,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x1f,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x3f,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x7f,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0xff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x1ff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x3ff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x7ff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0xfff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x1fff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x3fff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0x7fff,-0x20(%rbp)
jmp    1227 <ata_get_bits+0x117>
movl   $0xffff,-0x20(%rbp)
mov    -0x18(%rbp),%eax
mov    -0x1c(%rbp),%ecx
sar    %cl,%eax
and    -0x20(%rbp),%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<ata_get_bits>:
push   %rbp
push   %rbx
push   %rax
mov    %ecx,%ebp
mov    %edx,%ebx
call   1030 <ata_get_word@plt>
sub    %ebx,%ebp
xor    %edx,%edx
cmp    $0xf,%ebp
ja     1132 <ata_get_bits+0x22>
movslq %ebp,%rcx
lea    0xed1(%rip),%rdx
mov    (%rdx,%rcx,4),%edx
mov    %ebx,%ecx
sar    %cl,%eax
and    %edx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define i32 @ata_get_bits(i8* %0, i32 %1, i32 %2, i32 %3) {
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
store i8* %0, i8** %5
store i32 %1, i32* %6
store i32 %2, i32* %7
store i32 %3, i32* %8
%12 = load i8*, i8** %5
%13 = load i32, i32* %6
%14 = call i32 @ata_get_word(i8* %12, i32 %13)
store i32 %14, i32* %9
%15 = load i32, i32* %7
store i32 %15, i32* %10
store i32 0, i32* %11
%16 = load i32, i32* %8
%17 = load i32, i32* %7
%18 = sub nsw i32 %16, %17
%19 = add nsw i32 %18, 1
switch i32 %19, label %36 [
i32 1, label %20
i32 2, label %21
i32 3, label %22
i32 4, label %23
i32 5, label %24
i32 6, label %25
i32 7, label %26
i32 8, label %27
i32 9, label %28
i32 10, label %29
i32 11, label %30
i32 12, label %31
i32 13, label %32
i32 14, label %33
i32 15, label %34
i32 16, label %35
]
20: ; preds = %4
store i32 1, i32* %11
br label %36
21: ; preds = %4
store i32 3, i32* %11
br label %36
22: ; preds = %4
store i32 7, i32* %11
br label %36
23: ; preds = %4
store i32 15, i32* %11
br label %36
24: ; preds = %4
store i32 31, i32* %11
br label %36
25: ; preds = %4
store i32 63, i32* %11
br label %36
26: ; preds = %4
store i32 127, i32* %11
br label %36
27: ; preds = %4
store i32 255, i32* %11
br label %36
28: ; preds = %4
store i32 511, i32* %11
br label %36
29: ; preds = %4
store i32 1023, i32* %11
br label %36
30: ; preds = %4
store i32 2047, i32* %11
br label %36
31: ; preds = %4
store i32 4095, i32* %11
br label %36
32: ; preds = %4
store i32 8191, i32* %11
br label %36
33: ; preds = %4
store i32 16383, i32* %11
br label %36
34: ; preds = %4
store i32 32767, i32* %11
br label %36
35: ; preds = %4
store i32 65535, i32* %11
br label %36
36: ; preds = %4, %35, %34, %33, %32, %31, %30, %29, %28, %27, %26, %25, %24, %23, %22, %21, %20
%37 = load i32, i32* %9
%38 = load i32, i32* %10
%39 = ashr i32 %37, %38
%40 = load i32, i32* %11
%41 = and i32 %39, %40
ret i32 %41
}

LLVM IR (-O2):
@switch.table.ata_get_bits = [16 x i32] [i32 1, i32 3, i32 7, i32 15, i32 31, i32 63, i32 127, i32 255, i32 511, i32 1023, i32 2047, i32 4095, i32 8191, i32 16383, i32 32767, i32 65535]
define i32 @ata_get_bits(i8* %0, i32 %1, i32 %2, i32 %3) {
%5 = tail call i32 @ata_get_word(i8* %0, i32 %1)
%6 = sub nsw i32 %3, %2
%7 = icmp ult i32 %6, 16
br i1 %7, label %8, label %12
8: ; preds = %4
%9 = sext i32 %6 to i64
%10 = getelementptr inbounds [16 x i32], [16 x i32]* @switch.table.ata_get_bits, i64 0, i64 %9
%11 = load i32, i32* %10
br label %12
12: ; preds = %8, %4
%13 = phi i32 [ 0, %4 ], [ %11, %8 ]
%14 = ashr i32 %5, %2
%15 = and i32 %13, %14
ret i32 %15
}