// File: lukasz-wiecaszek[P]h264iframedecoder/picture_cabac.cpp
// Function: ymn::h264::picture_cabac::intraNxN_pred_mode_cache_init(unsigned int)
void picture_cabac::intraNxN_pred_mode_cache_init(uint32_t constrained_intra_pred_flag)
{
    const mb* curr_mb = m_context_variables.curr_mb;
    const int* left_blocks = m_context_variables.left_blocks;
    mb_cache& ipm_cache = m_context_variables.intraNxN_pred_mode_cache;

    if (curr_mb->top && MB_IS_INTRA_NxN(curr_mb->top->type)) {
        const mb* top = curr_mb->top;

        if (MB_IS_INTRA_4x4(top->type))
        {
            ipm_cache[0 * 8 + 4] = top->intra_luma_pred_mode.m4x4[3 * 4 + 0];
            ipm_cache[0 * 8 + 5] = top->intra_luma_pred_mode.m4x4[3 * 4 + 1];
            ipm_cache[0 * 8 + 6] = top->intra_luma_pred_mode.m4x4[3 * 4 + 2];
            ipm_cache[0 * 8 + 7] = top->intra_luma_pred_mode.m4x4[3 * 4 + 3];
        }
        else
        {
            ipm_cache[0 * 8 + 4] = top->intra_luma_pred_mode.m8x8[2];
            ipm_cache[0 * 8 + 5] = top->intra_luma_pred_mode.m8x8[2];
            ipm_cache[0 * 8 + 6] = top->intra_luma_pred_mode.m8x8[3];
            ipm_cache[0 * 8 + 7] = top->intra_luma_pred_mode.m8x8[3];
        }
    }
    else {
        int pred = MB_INTRA_PRED_LUMA_NxN_DC;

        if (curr_mb->top == nullptr || (MB_IS_INTER(curr_mb->top->type) && constrained_intra_pred_flag))
            pred = -1;

        ipm_cache[0 * 8 + 4] = pred;
        ipm_cache[0 * 8 + 5] = pred;
        ipm_cache[0 * 8 + 6] = pred;
        ipm_cache[0 * 8 + 7] = pred;
    }

    for (int i = 0; i < 2; ++i) {
        if (curr_mb->left_pair[i] && MB_IS_INTRA_NxN(curr_mb->left_pair[i]->type)) {
            const mb* left = curr_mb->left_pair[i];

            if (MB_IS_INTRA_4x4(left->type)) {
                ipm_cache[3 + 1 * 8 + 2 * 8 * i] =
                    left->intra_luma_pred_mode.m4x4[3 + left_blocks[0 + 2 * i] * 4];

                ipm_cache[3 + 2 * 8 + 2 * 8 * i] =
                    left->intra_luma_pred_mode.m4x4[3 + left_blocks[1 + 2 * i] * 4];
            }
            else {
                ipm_cache[3 + 1 * 8 + 2 * 8 * i] =
                    left->intra_luma_pred_mode.m8x8[left_blocks[0 + 2 * i] | 1];

                ipm_cache[3 + 2 * 8 + 2 * 8 * i] =
                    left->intra_luma_pred_mode.m8x8[left_blocks[1 + 2 * i] | 1];
            }
        }
        else {
            int pred = MB_INTRA_PRED_LUMA_NxN_DC;

            if (curr_mb->left_pair[i] == nullptr|| (MB_IS_INTER(curr_mb->left_pair[i]->type) && constrained_intra_pred_flag))
                pred = -1;

            ipm_cache[3 + 1 * 8 + 2 * 8 * i] = pred;
            ipm_cache[3 + 2 * 8 + 2 * 8 * i] = pred;
        }
    }
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x50(%rsp)
movl %esi, 0x4c(%rsp)
movq 0x50(%rsp), %rax
movq 0x28(%rax), %rcx
movq %rcx, 0x40(%rsp)
movq 0x48(%rax), %rcx
movq %rcx, 0x38(%rsp)
addq $0x18, %rax
addq $0x40, %rax
movq %rax, 0x30(%rsp)
movq 0x40(%rsp), %rax
cmpq $0x0, 0x50(%rax)
je 0x1f99d
movq 0x40(%rsp), %rax
movq 0x50(%rax), %rax
movl 0x10(%rax), %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0x1f99d
movq 0x40(%rsp), %rax
movq 0x50(%rax), %rax
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rax
movl 0x10(%rax), %eax
andl $0x3, %eax
cmpl $0x1, %eax
jne 0x1f914
movq 0x28(%rsp), %rax
movb 0x64(%rax), %al
movb %al, 0x10(%rsp)
movq 0x30(%rsp), %rdi
movl $0x4, %esi
callq 0x22380
movb 0x10(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x65(%rax), %al
movb %al, 0x11(%rsp)
movq 0x30(%rsp), %rdi
movl $0x5, %esi
callq 0x22380
movb 0x11(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x66(%rax), %al
movb %al, 0x12(%rsp)
movq 0x30(%rsp), %rdi
movl $0x6, %esi
callq 0x22380
movb 0x12(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x67(%rax), %al
movb %al, 0x13(%rsp)
movq 0x30(%rsp), %rdi
movl $0x7, %esi
callq 0x22380
movb 0x13(%rsp), %cl
movb %cl, (%rax)
jmp 0x1f998
movq 0x28(%rsp), %rax
movb 0x5a(%rax), %al
movb %al, 0xc(%rsp)
movq 0x30(%rsp), %rdi
movl $0x4, %esi
callq 0x22380
movb 0xc(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x5a(%rax), %al
movb %al, 0xd(%rsp)
movq 0x30(%rsp), %rdi
movl $0x5, %esi
callq 0x22380
movb 0xd(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x5b(%rax), %al
movb %al, 0xe(%rsp)
movq 0x30(%rsp), %rdi
movl $0x6, %esi
callq 0x22380
movb 0xe(%rsp), %cl
movb %cl, (%rax)
movq 0x28(%rsp), %rax
movb 0x5b(%rax), %al
movb %al, 0xf(%rsp)
movq 0x30(%rsp), %rdi
movl $0x7, %esi
callq 0x22380
movb 0xf(%rsp), %cl
movb %cl, (%rax)
jmp 0x1fa4a
movl $0x2, 0x24(%rsp)
movq 0x40(%rsp), %rax
cmpq $0x0, 0x50(%rax)
je 0x1f9ce
movq 0x40(%rsp), %rax
movq 0x50(%rax), %rax
movl 0x10(%rax), %eax
andl $0xf0, %eax
cmpl $0x0, %eax
je 0x1f9d6
cmpl $0x0, 0x4c(%rsp)
je 0x1f9d6
movl $0xffffffff, 0x24(%rsp) # imm = 0xFFFFFFFF
movl 0x24(%rsp), %eax
movb %al, 0x8(%rsp)
movq 0x30(%rsp), %rdi
movl $0x4, %esi
callq 0x22380
movb 0x8(%rsp), %cl
movb %cl, (%rax)
movl 0x24(%rsp), %eax
movb %al, 0x9(%rsp)
movq 0x30(%rsp), %rdi
movl $0x5, %esi
callq 0x22380
movb 0x9(%rsp), %cl
movb %cl, (%rax)
movl 0x24(%rsp), %eax
movb %al, 0xa(%rsp)
movq 0x30(%rsp), %rdi
movl $0x6, %esi
callq 0x22380
movb 0xa(%rsp), %cl
movb %cl, (%rax)
movl 0x24(%rsp), %eax
movb %al, 0xb(%rsp)
movq 0x30(%rsp), %rdi
movl $0x7, %esi
callq 0x22380
movb 0xb(%rsp), %cl
movb %cl, (%rax)
movl $0x0, 0x20(%rsp)
cmpl $0x2, 0x20(%rsp)
jge 0x1fc7a
movq 0x40(%rsp), %rax
movslq 0x20(%rsp), %rcx
cmpq $0x0, 0x40(%rax,%rcx,8)
je 0x1fbd9
movq 0x40(%rsp), %rax
movslq 0x20(%rsp), %rcx
movq 0x40(%rax,%rcx,8), %rax
movl 0x10(%rax), %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0x1fbd9
movq 0x40(%rsp), %rax
movslq 0x20(%rsp), %rcx
movq 0x40(%rax,%rcx,8), %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rax
movl 0x10(%rax), %eax
andl $0x3, %eax
cmpl $0x1, %eax
jne 0x1fb4c
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
movl 0x20(%rsp), %edx
shll %edx
addl $0x0, %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
shll $0x2, %ecx
addl $0x3, %ecx
movslq %ecx, %rcx
movb 0x58(%rax,%rcx), %al
movb %al, 0x6(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0xb, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x6(%rsp), %cl
movb %cl, (%rax)
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
movl 0x20(%rsp), %edx
shll %edx
addl $0x1, %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
shll $0x2, %ecx
addl $0x3, %ecx
movslq %ecx, %rcx
movb 0x58(%rax,%rcx), %al
movb %al, 0x7(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0x13, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x7(%rsp), %cl
movb %cl, (%rax)
jmp 0x1fbd4
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
movl 0x20(%rsp), %edx
shll %edx
addl $0x0, %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
orl $0x1, %ecx
movslq %ecx, %rcx
movb 0x58(%rax,%rcx), %al
movb %al, 0x4(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0xb, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x4(%rsp), %cl
movb %cl, (%rax)
movq 0x18(%rsp), %rax
movq 0x38(%rsp), %rcx
movl 0x20(%rsp), %edx
shll %edx
addl $0x1, %edx
movslq %edx, %rdx
movl (%rcx,%rdx,4), %ecx
orl $0x1, %ecx
movslq %ecx, %rcx
movb 0x58(%rax,%rcx), %al
movb %al, 0x5(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0x13, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x5(%rsp), %cl
movb %cl, (%rax)
jmp 0x1fc68
movl $0x2, 0x14(%rsp)
movq 0x40(%rsp), %rax
movslq 0x20(%rsp), %rcx
cmpq $0x0, 0x40(%rax,%rcx,8)
je 0x1fc16
movq 0x40(%rsp), %rax
movslq 0x20(%rsp), %rcx
movq 0x40(%rax,%rcx,8), %rax
movl 0x10(%rax), %eax
andl $0xf0, %eax
cmpl $0x0, %eax
je 0x1fc1e
cmpl $0x0, 0x4c(%rsp)
je 0x1fc1e
movl $0xffffffff, 0x14(%rsp) # imm = 0xFFFFFFFF
movl 0x14(%rsp), %eax
movb %al, 0x2(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0xb, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x2(%rsp), %cl
movb %cl, (%rax)
movl 0x14(%rsp), %eax
movb %al, 0x3(%rsp)
movq 0x30(%rsp), %rdi
movl 0x20(%rsp), %eax
shll $0x4, %eax
addl $0x13, %eax
movslq %eax, %rsi
callq 0x22380
movb 0x3(%rsp), %cl
movb %cl, (%rax)
jmp 0x1fc6a
movl 0x20(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x20(%rsp)
jmp 0x1fa52
addq $0x58, %rsp
retq
nop