// File: /workspace/github_cpp_makefile_star2_O3/lukasz-wiecaszek[P]h264iframedecoder/picture_cabac.cpp
// Function: ymn::h264::picture_cabac::decode_residual_block(int*, ymn::h264::ctx_block_cat_e, int, unsigned char const*, int)
void picture_cabac::decode_residual_block(dctcoeff* block,
                                          const enum ctx_block_cat_e ctxBlockCat,
                                          const int idx,
                                          const uint8_t* scantable,
                                          const int max_coeff)
{
    /* Table 9-43 � Mapping of scanning position to ctxIdxInc for ctxBlockCat == 5, 9, or 13 */
    static const int significant_coeff_flag_offset_8x8[2][63] =
    {
        { 0, 1, 2, 3, 4, 5, 5, 4, 4, 3, 3, 4, 4, 4, 5, 5,
          4, 4, 4, 4, 3, 3, 6, 7, 7, 7, 8, 9,10, 9, 8, 7,
          7, 6,11,12,13,11, 6, 7, 8, 9,14,10, 9, 8, 6,11,
         12,13,11, 6, 9,14,10, 9,11,12,13,11,14,10,12 },
        { 0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 7, 8, 4, 5,
          6, 9,10,10, 8,11,12,11, 9, 9,10,10, 8,11,12,11,
          9, 9,10,10, 8,11,12,11, 9, 9,10,10, 8,13,13, 9,
          9,10,10, 8,13,13, 9, 9,10,10,14,14,14,14,14 }
    };

    /* Table 9-43 � Mapping of scanning position to ctxIdxInc for ctxBlockCat == 5, 9, or 13 */
    static const int last_significant_coeff_flag_offset_8x8[63] =
    {
        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
        3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
        5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8
    };

    int i;
    int index[64];
    int coeff_count = 0;
    const bool is_dc = (idx >= (16 * CC_MAX));

    if (max_coeff != 64) {
        for(i = 0; i < max_coeff - 1; ++i) {
            if (decode_significant_coeff_flag(ctxBlockCat, i)) {
                index[coeff_count++] = i;
                if (decode_last_significant_coeff_flag(ctxBlockCat, i))
                    i = max_coeff;
            }
        }
    }
    else {
        const bool is_field_mb = m_context_variables.mb_field_decoding_flag;
        for(i = 0; i < max_coeff - 1; ++i) {
            if (decode_significant_coeff_flag(ctxBlockCat, significant_coeff_flag_offset_8x8[is_field_mb][i])) {
                index[coeff_count++] = i;
                if (decode_last_significant_coeff_flag(ctxBlockCat, last_significant_coeff_flag_offset_8x8[i]))
                    i = max_coeff;
            }
        }
    }
    if (i == max_coeff - 1)
        index[coeff_count++] = i;

    if (is_dc) {
        mb_cache& nzc_cache = m_context_variables.non_zero_count_cache[idx - 16 * CC_MAX];
        nzc_cache[0] = coeff_count;
    }
    else {
        mb_cache& nzc_cache = m_context_variables.non_zero_count_cache[idx / 16];
        const int cache_idx = mb_cache_idx[idx % 16];
        if (max_coeff == 64)
            mb_cache_fill_rectangle_2x2(nzc_cache, cache_idx, coeff_count);
        else
            nzc_cache[cache_idx] = coeff_count;
    }

    /* If binIdx is equal to 0, ctxIdxInc is derived by
       ctxIdxInc = ((numDecodAbsLevelGt1 != 0) ? 0: Min(4, 1 + numDecodAbsLevelEq1)) */
    static const int coeff_abs_level_bin_idx_eq0[8] =
    {
        1, 2, 3, 4, 0, 0, 0, 0
    };

    /* Otherwise (binIdx is greater than 0), ctxIdxInc is derived by
       ctxIdxInc = 5 + Min(4 - ((ctxBlockCat == 3) ? 1 : 0), numDecodAbsLevelGt1) */
    static const int coeff_abs_level_bin_idx_gt0[2][8] =
    {
        /* ctxBlockCat == 3 */
        { 5, 5, 5, 5, 6, 7, 8, 8 },
        /* ctxBlockCat != 3 */
        { 5, 5, 5, 5, 6, 7, 8, 9 },
    };

    static const int coeff_abs_level_transition[2][8] =
    {
        /* update node ctx after decoding a coeff_abs_level == 1 */
        { 1, 2, 3, 3, 4, 5, 6, 7 },
        /* update node ctx after decoding a coeff_abs_level > 1 */
        { 4, 4, 4, 4, 5, 6, 7, 7 }
    };

    for (int node = 0; coeff_count > 0; ) {
        int ctxIdxInc;
        int coeff_abs_level;
        int pos = scantable[index[--coeff_count]];

        ctxIdxInc = coeff_abs_level_bin_idx_eq0[node];
        if (decode_coeff_abs_level_minus1(ctxBlockCat, ctxIdxInc) == 0) {
            coeff_abs_level = 1;
        }
        else {
            coeff_abs_level = 2;
            ctxIdxInc = coeff_abs_level_bin_idx_gt0[ctxBlockCat == 3 ? 0 : 1][node];
            while (coeff_abs_level < 15 && decode_coeff_abs_level_minus1(ctxBlockCat, ctxIdxInc))
                coeff_abs_level++;

#if 0
            if (coeff_abs_level >= 15) {
                int j = 0;
                while (m_cabac_decoder.decode_bypass())
                    j++;

                coeff_abs_level = 1;
                while (j--)
                    coeff_abs_level += coeff_abs_level + m_cabac_decoder.decode_bypass();

                coeff_abs_level += 14;
            }
#endif
        }

        block[pos] = (m_cabac_decoder.decode_bypass() == 0) ? coeff_abs_level : -coeff_abs_level;
        node = coeff_abs_level_transition[coeff_abs_level == 1 ? 0 : 1][node];
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x138, %rsp            # imm = 0x138
movq %r8, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movq %rdi, %r15
cmpl $0x40, %r9d
jne 0x176af
movq %rcx, 0x10(%rsp)
movq %r9, 0x8(%rsp)
movzbl 0x19(%r15), %eax
leaq 0xdc0(%r15), %rbp
movl %edx, 0x4(%rsp)
movl %edx, %ebx
imulq $0xfc, %rax, %rax
movq %rax, 0x18(%rsp)
xorl %r14d, %r14d
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
xorl %r12d, %r12d
incl %r13d
movq 0x18(%rsp), %rax
addq %r14, %rax
movzbl 0x19(%r15), %ecx
imulq $0x38, %rcx, %rcx
leaq 0x57db(%rip), %rdx      # 0x1ce20
addq %rdx, %rcx
movl (%rcx,%rbx,4), %esi
leaq 0x58ee(%rip), %rcx      # 0x1cf40
addl (%rcx,%rax), %esi
movq %rbp, %rdi
callq 0x7ac8
testl %eax, %eax
je 0x1769d
movslq %r12d, %rax
incl %r12d
movl %r13d, 0x30(%rsp,%rax,4)
movzbl 0x19(%r15), %eax
imulq $0x38, %rax, %rax
leaq 0x5814(%rip), %rcx      # 0x1ce90
addq %rcx, %rax
movl (%rax,%rbx,4), %esi
leaq 0x5ab7(%rip), %rax      # 0x1d140
addl (%r14,%rax), %esi
movq %rbp, %rdi
callq 0x7ac8
testl %eax, %eax
jne 0x17755
addq $0x4, %r14
cmpl $0x3e, %r13d
jb 0x1762a
incl %r13d
jmp 0x1775b
leal -0x1(%r9), %ebx
xorl %r12d, %r12d
cmpl $0x2, %r9d
jl 0x17750
movq %rcx, 0x10(%rsp)
movq %r9, 0x8(%rsp)
leaq 0xdc0(%r15), %rbp
movl %edx, 0x4(%rsp)
movl %edx, %r14d
xorl %r13d, %r13d
xorl %r12d, %r12d
movzbl 0x19(%r15), %eax
imulq $0x38, %rax, %rax
leaq 0x5732(%rip), %rcx      # 0x1ce20
addq %rcx, %rax
movl (%rax,%r14,4), %esi
addl %r13d, %esi
movq %rbp, %rdi
callq 0x7ac8
testl %eax, %eax
je 0x1773d
movslq %r12d, %rax
movl %r13d, 0x30(%rsp,%rax,4)
movzbl 0x19(%r15), %eax
imulq $0x38, %rax, %rax
leaq 0x5774(%rip), %rcx      # 0x1ce90
addq %rcx, %rax
movl (%rax,%r14,4), %esi
addl %r13d, %esi
movq %rbp, %rdi
callq 0x7ac8
testl %eax, %eax
je 0x1773a
movq 0x8(%rsp), %rax
movl %eax, %r13d
incl %r12d
incl %r13d
cmpl %ebx, %r13d
jl 0x176de
movl 0x4(%rsp), %edx
movq 0x8(%rsp), %r9
jmp 0x17768
xorl %r13d, %r13d
jmp 0x1776d
movl $0x41, %r13d
movq 0x8(%rsp), %r9
leal -0x1(%r9), %ebx
movl 0x4(%rsp), %edx
movq 0x10(%rsp), %rcx
cmpl %ebx, %r13d
jne 0x1777c
movslq %r12d, %rax
incl %r12d
movl %ebx, 0x30(%rsp,%rax,4)
leaq 0x80(%r15), %rax
cmpl $0x30, %ecx
jl 0x17795
addl $-0x30, %ecx
leaq (%rcx,%rcx,4), %rcx
movb %r12b, (%rax,%rcx,8)
jmp 0x177e1
leal 0xf(%rcx), %edi
testl %ecx, %ecx
cmovnsl %ecx, %edi
movl %edi, %esi
andl $-0x10, %esi
subl %esi, %ecx
sarl $0x4, %edi
movslq %edi, %rsi
leaq (%rsi,%rsi,4), %rsi
leaq (%rax,%rsi,8), %rax
movslq %ecx, %rcx
leaq 0x5614(%rip), %rsi      # 0x1cdd0
movzbl (%rcx,%rsi), %ecx
cmpl $0x40, %r9d
jne 0x177dd
movzbl %r12b, %edi
movl %r12d, %esi
shll $0x8, %esi
orl %edi, %esi
movw %si, (%rax,%rcx)
movw %si, 0x8(%rax,%rcx)
jmp 0x177e1
movb %r12b, (%rax,%rcx)
testl %r12d, %r12d
jle 0x178d1
addq $0xdc0, %r15            # imm = 0xDC0
movl %edx, %eax
leaq 0x5706(%rip), %rcx      # 0x1cf00
movl (%rcx,%rax,4), %r13d
xorl %ecx, %ecx
cmpl $0x3, %edx
setne %cl
movl %r12d, %ebx
xorl %eax, %eax
shll $0x5, %ecx
leaq 0x5a2b(%rip), %rdx      # 0x1d240
addq %rcx, %rdx
movq %rdx, 0x8(%rsp)
movl %r13d, 0x18(%rsp)
movslq 0x2c(%rsp,%rbx,4), %rcx
movq 0x28(%rsp), %rdx
movzbl (%rdx,%rcx), %r12d
movslq %eax, %r14
leaq 0x5c55(%rip), %rax      # 0x1d490
movl (%rax,%r14,4), %esi
addl %r13d, %esi
movq %r15, %rdi
callq 0x7ac8
testl %eax, %eax
je 0x1787f
movq 0x8(%rsp), %rax
movl (%rax,%r14,4), %ebp
addl %r13d, %ebp
movl $0x2, %r13d
movq %r15, %rdi
movl %ebp, %esi
callq 0x7ac8
testl %eax, %eax
je 0x17885
incl %r13d
cmpl $0xf, %r13d
jne 0x17860
movl $0xf, %r13d
jmp 0x17885
movl $0x1, %r13d
leaq -0x1(%rbx), %rbp
movq %r15, %rdi
callq 0x7a1a
movl %r13d, %ecx
negl %ecx
testl %eax, %eax
cmovel %r13d, %ecx
movq 0x20(%rsp), %rax
movl %ecx, (%rax,%r12,4)
xorl %eax, %eax
cmpl $0x1, %r13d
setne %al
shll $0x5, %eax
leaq 0x59c8(%rip), %rcx      # 0x1d280
addq %rcx, %rax
movl (%rax,%r14,4), %eax
cmpq $0x1, %rbx
movq %rbp, %rbx
movl 0x18(%rsp), %r13d
jg 0x17822
addq $0x138, %rsp            # imm = 0x138
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop