// File: /workspace/github_c_makefile_star2_O3/samtools[P]htslib/cram/cram_codecs.c
// Function: get_bits_MSB
static inline int64_t get_bits_MSB(cram_block *block, int nbits) {
    uint64_t val = 0;
    int i;

#if 0
    // Fits within the current byte */
    if (nbits <= block->bit+1) {
        val = (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
        if ((block->bit -= nbits) == -1) {
            block->bit = 7;
            block->byte++;
        }
        return val;
    }

    // partial first byte
    val = block->data[block->byte] & ((1<<(block->bit+1))-1);
    nbits -= block->bit+1;
    block->bit = 7;
    block->byte++;

    // whole middle bytes
    while (nbits >= 8) {
        val = (val << 8) | block->data[block->byte++];
        nbits -= 8;
    }

    val <<= nbits;
    val |= (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
    block->bit -= nbits;
    return val;
#endif

#if 0
    /* Inefficient implementation! */
    //printf("{");
    for (i = 0; i < nbits; i++)
        //val = (val << 1) | get_bit_MSB(block);
        GET_BIT_MSB(block, val);
#endif

#if 1
    /* Combination of 1st two methods */
    if (nbits <= block->bit+1) {
        val = (block->data[block->byte]>>(block->bit-(nbits-1))) & ((1<<nbits)-1);
        if ((block->bit -= nbits) == -1) {
            block->bit = 7;
            block->byte++;
        }
        return val;
    }

    switch(nbits) {
//  case 15: GET_BIT_MSB(block, val); // fall through
//  case 14: GET_BIT_MSB(block, val); // fall through
//  case 13: GET_BIT_MSB(block, val); // fall through
//  case 12: GET_BIT_MSB(block, val); // fall through
//  case 11: GET_BIT_MSB(block, val); // fall through
//  case 10: GET_BIT_MSB(block, val); // fall through
//  case  9: GET_BIT_MSB(block, val); // fall through
    case  8: GET_BIT_MSB(block, val); // fall through
    case  7: GET_BIT_MSB(block, val); // fall through
    case  6: GET_BIT_MSB(block, val); // fall through
    case  5: GET_BIT_MSB(block, val); // fall through
    case  4: GET_BIT_MSB(block, val); // fall through
    case  3: GET_BIT_MSB(block, val); // fall through
    case  2: GET_BIT_MSB(block, val); // fall through
    case  1: GET_BIT_MSB(block, val);
        break;

    default:
        for (i = 0; i < nbits; i++)
            //val = (val << 1) | get_bit_MSB(block);
            GET_BIT_MSB(block, val);
    }
#endif

    //printf("=0x%x}", val);

    return val;
}

// Assembly:
movl 0x38(%rdi), %edx
leal 0x1(%rdx), %eax
cmpl %esi, %eax
jge 0x8cf20
leal -0x1(%rsi), %eax
cmpl $0x7, %eax
ja 0x8d114
leaq 0x15908(%rip), %rcx     # 0xa2810
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %rcx
xorl %esi, %esi
jmp 0x8d0e9
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %r8
movzbl (%rax,%r8), %r9d
subl %esi, %edx
leal 0x1(%rdx), %ecx
shrl %cl, %r9d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %esi, %ecx
shll %cl, %eax
notl %eax
andl %r9d, %eax
movl %edx, 0x38(%rdi)
incl %edx
jne 0x8d153
movl $0x7, 0x38(%rdi)
incq %r8
movq %r8, 0x30(%rdi)
retq
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %rcx
xorl %esi, %esi
jmp 0x8d037
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %rcx
xorl %esi, %esi
jmp 0x8d090
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %r8
xorl %esi, %esi
jmp 0x8d065
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %r8
movzbl (%rax,%r8), %esi
movl %edx, %ecx
shrl %cl, %esi
xorl %ecx, %ecx
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %cl
addq %r8, %rcx
movq %rcx, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
andl $0x2, %esi
jmp 0x8cfde
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %r8
xorl %esi, %esi
jmp 0x8d0be
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %r8
xorl %esi, %esi
jmp 0x8d00c
movq 0x20(%rdi), %rax
movq 0x30(%rdi), %rcx
xorl %esi, %esi
movzbl (%rax,%rcx), %r8d
xorl %r9d, %r9d
btl %edx, %r8d
setb %r9b
orl %r9d, %esi
xorl %r8d, %r8d
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %r8b
addq %rcx, %r8
movq %r8, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%r8), %ecx
xorl %r9d, %r9d
btl %edx, %ecx
setb %r9b
orl %r9d, %esi
xorl %ecx, %ecx
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %cl
addq %r8, %rcx
movq %rcx, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%rcx), %r8d
xorl %r9d, %r9d
btl %edx, %r8d
setb %r9b
orl %r9d, %esi
xorl %r8d, %r8d
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %r8b
addq %rcx, %r8
movq %r8, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%r8), %ecx
xorl %r9d, %r9d
btl %edx, %ecx
setb %r9b
orl %r9d, %esi
xorl %ecx, %ecx
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %cl
addq %r8, %rcx
movq %rcx, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%rcx), %r8d
xorl %r9d, %r9d
btl %edx, %r8d
setb %r9b
orl %r9d, %esi
xorl %r8d, %r8d
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %r8b
addq %rcx, %r8
movq %r8, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%r8), %ecx
xorl %r9d, %r9d
btl %edx, %ecx
setb %r9b
orl %r9d, %esi
xorl %ecx, %ecx
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %cl
addq %r8, %rcx
movq %rcx, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
addl %esi, %esi
movzbl (%rax,%rcx), %r8d
xorl %eax, %eax
btl %edx, %r8d
setb %al
orq %rsi, %rax
leal -0x1(%rdx), %esi
xorl %r8d, %r8d
testl %edx, %edx
setle %r8b
addq %rcx, %r8
movq %r8, 0x30(%rdi)
andl $0x7, %esi
movl %esi, 0x38(%rdi)
retq
testl %esi, %esi
jle 0x8d154
movq 0x20(%rdi), %rcx
movq 0x30(%rdi), %r8
xorl %eax, %eax
movzbl (%rcx,%r8), %r9d
xorl %r10d, %r10d
btl %edx, %r9d
setb %r10b
leaq (%r10,%rax,2), %rax
xorl %r9d, %r9d
testl %edx, %edx
leal -0x1(%rdx), %edx
setle %r9b
addq %r9, %r8
movq %r8, 0x30(%rdi)
andl $0x7, %edx
movl %edx, 0x38(%rdi)
decl %esi
jne 0x8d122
retq
xorl %eax, %eax
retq