// File: /workspace/github_cpp_makefile_star2_O2/ruankotovich[P]B-Tree/src/secondarybtree.cpp
// Function: SecondaryBTree::insertRecursive(SecondaryBTreeDataMap&, SecondaryBTreeNodeReinterpret*, int, _IO_FILE*)
SecondaryBTreeRecursionResponse SecondaryBTree::insertRecursive(SecondaryBTreeDataMap& key, SecondaryBTreeNodeReinterpret* nodeReinterpretation, int offset, FILE* indexFile)
{
    for (unsigned short i = 0; i < nodeReinterpretation->node.count; ++i) {
        if (nodeReinterpretation->node.keys[i] == key) return SUCCESSFUL_TREE_INSERTION;
    }

    if (nodeReinterpretation->node.isLeaf()) {

        if (nodeReinterpretation->node.hasRoom()) {
            nodeReinterpretation->node.insert(key);
            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
            return SUCCESSFUL_TREE_INSERTION;
        }

        SecondaryBTreeNode* splitLeaf = new SecondaryBTreeNode(SECONDARY_MAX_KEYS);
        SecondaryBTreeDataMap promoted;

        // elege o promoted e manipula os vetores resultantes da operação do splitLeaf.
        SecondaryBTreeDataMap leftMiddleKey = nodeReinterpretation->node.keys[SECONDARY_LEFT_MIDDLE_KEY];
        SecondaryBTreeDataMap rightMiddleKey = nodeReinterpretation->node.keys[SECONDARY_RIGHT_MIDDLE_KEY];

        splitLeaf->count = nodeReinterpretation->node.count = SECONDARY_HALF_MAX_KEYS;

        switch (relativeKeyPosition(key, leftMiddleKey, rightMiddleKey)) {
        case RELATIVE_LEFT: {
            promoted = leftMiddleKey;
            --nodeReinterpretation->node.count;

            nodeReinterpretation->node.insert(key);

            for (int i = SECONDARY_HALF_MAX_KEYS, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            }
        } // não esquecer de manipular os blockPointes para nós não-folha
        break;

        case RELATIVE_RIGHT: {
            promoted = rightMiddleKey;
            --splitLeaf->count;

            for (int i = SECONDARY_RIGHT_MIDDLE_KEY + 1, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            } // não esquecer de manipular os blockPointes para nós não-folha

            splitLeaf->insert(key);
        } break;

        case RELATIVE_MIDDLE: {
            promoted = key;

            for (int i = SECONDARY_HALF_MAX_KEYS, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            }
        } // não esquecer de manipular os blockPointes para nós não-folha

        break;
        }

        writeBackNode(&nodeReinterpretation->node, offset, indexFile);
        int offset = writeNewNode(splitLeaf, indexFile);

        delete splitLeaf; // deleta da memória principal pois já foi salvo no disco

        // return { true, { promoted, offset } };
        return SecondaryBTreeRecursionResponse(true, promoted, offset);
    }
    //key.key[299] = '\0';
    int result = upperBound(nodeReinterpretation->node.keys, nodeReinterpretation->node.count, key); // [TROCAR]

    //auto resultPair = u(nodeReinterpretation->node.keys, nodeReinterpretation->node.count, key);
    int childNodeOffset;

    if (result >= nodeReinterpretation->node.count) {
        childNodeOffset = result;
        result = nodeReinterpretation->node.count - 1;
    }

    childNodeOffset = ((key < nodeReinterpretation->node.keys[result]) ? nodeReinterpretation->node.blockPointers[result] : nodeReinterpretation->node.blockPointers[result + 1]);

    SecondaryBTreeNodeReinterpret* retrieveNode = new SecondaryBTreeNodeReinterpret();
    fseek(indexFile, sizeof(AbstractBlock_t) * childNodeOffset, SEEK_SET);
    fread(&retrieveNode->block, sizeof(AbstractBlock_t), 1, indexFile);

    auto resultRecursion = insertRecursive(key, retrieveNode, childNodeOffset, indexFile);
    delete retrieveNode;

    if (resultRecursion.hasBeenSplit) { // caso em que veio um valor promovido e um blockPointer
        //caso 1 - tem espaço para inserir o promovido
        if (nodeReinterpretation->node.hasRoom()) {
            //o + 1 é para não realizar essa soma em toda iteração do for logo abaixo
            int rightIndexInserted = nodeReinterpretation->node.insert(resultRecursion.promotedKey) + 1;

            for (unsigned short i = nodeReinterpretation->node.countPointers; i > rightIndexInserted; --i) {
                nodeReinterpretation->node.blockPointers[i] = nodeReinterpretation->node.blockPointers[i - 1];
            }

            nodeReinterpretation->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;
            ++nodeReinterpretation->node.countPointers;

            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
        } else { // caso 2 - não tem espaço para inserir o promovido -> fazer o split com remanejamento de chaves
            SecondaryBTreeNodeReinterpret* split = new SecondaryBTreeNodeReinterpret();
            SecondaryBTreeDataMap promoted;

            // elege o promoted e manipula os vetores resultantes da operação do split.
            SecondaryBTreeDataMap leftMiddleKey = nodeReinterpretation->node.keys[SECONDARY_LEFT_MIDDLE_KEY];
            SecondaryBTreeDataMap rightMiddleKey = nodeReinterpretation->node.keys[SECONDARY_RIGHT_MIDDLE_KEY];

            split->node.count = nodeReinterpretation->node.count = SECONDARY_HALF_MAX_KEYS; // remoção lógica exatamente na metade

            //como está cheio, vai metade dos elementos para cada bloco, contnado com o split.
            // se vai metade, haverá metade + 1 ponteiros para bloco preenchidos.
            split->node.countPointers = nodeReinterpretation->node.countPointers = SECONDARY_HALF_MAX_KEYS + 1;

            switch (relativeKeyPosition(resultRecursion.promotedKey, leftMiddleKey, rightMiddleKey)) {
            case RELATIVE_LEFT: {
                promoted = leftMiddleKey;

                --nodeReinterpretation->node.count;

                // índice do ponteiro mais à direita do vetor blockPointers
                int greaterNodeBlockPointer = nodeReinterpretation->node.blockPointers[nodeReinterpretation->node.countPointers - 1]; // a subtração tem a ver com índice

                //índice em que foi inserido o promovido no nó já existente
                int rightIndexInserted = nodeReinterpretation->node.insert(resultRecursion.promotedKey) + 1;

                //remanejar os blockPoints
                for (int i = nodeReinterpretation->node.countPointers - 1; i > rightIndexInserted; --i) {
                    nodeReinterpretation->node.blockPointers[i] = nodeReinterpretation->node.blockPointers[i - 1];
                }

                nodeReinterpretation->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;

                for (int i = SECONDARY_HALF_MAX_KEYS, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j + 1] = nodeReinterpretation->node.blockPointers[i + 1];
                } // não esquecer de manipular os blockPointes para nós não-folha

                split->node.blockPointers[0] = greaterNodeBlockPointer;
            } break;

            case RELATIVE_RIGHT: {
                promoted = rightMiddleKey;
                --split->node.count;
                // não é preciso modificar o countPointers nem o count do node aqui porque eles já foram atribuidos ali em cima,
                // então a remoção lógica já foi feita

                for (int i = SECONDARY_RIGHT_MIDDLE_KEY + 1, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j] = nodeReinterpretation->node.blockPointers[i];
                } // não esquecer de manipular os blockPointes para nós não-folha/

                split->node.blockPointers[SECONDARY_HALF_MAX_KEYS - 1] = nodeReinterpretation->node.blockPointers[SECONDARY_MAX_KEYS];
                int rightIndexInserted = split->node.insert(resultRecursion.promotedKey) + 1;

                //remanejar os blockPoints
                for (unsigned short i = split->node.countPointers - 1; i > rightIndexInserted; --i) {
                    split->node.blockPointers[i] = split->node.blockPointers[i - 1];
                }

                split->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;
            } break;

            case RELATIVE_MIDDLE: {
                promoted = resultRecursion.promotedKey;

                for (int i = SECONDARY_HALF_MAX_KEYS, j = 0; i < SECONDARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j + 1] = nodeReinterpretation->node.blockPointers[i + 1];
                } // não esquecer de manipular os blockPointes para nós não-folha
                split->node.blockPointers[0] = resultRecursion.newBlockOffset;
            } break;
            }

            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
            int offset = writeNewNode(&split->node, indexFile);
            delete split; // deleta da memória principal pois já foi salvo no disco
            return SecondaryBTreeRecursionResponse(true, promoted, offset);
        }
    }

    return SUCCESSFUL_TREE_INSERTION;
    // return SecondaryBTreeRecursionResponse(false, 0, 0);
    // return { false, { 0, 0 } };*/
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4f8, %rsp            # imm = 0x4F8
movq %r9, 0x18(%rsp)
movl %r8d, 0x14(%rsp)
movq %rdx, %r12
movq %rdi, 0x20(%rsp)
movzwl (%rcx), %ebx
movq %rcx, 0x8(%rsp)
leaq 0x4(%rcx), %rbp
leaq 0x1(%rbx), %r14
movq %rbp, %rdi
decq %r14
je 0x19f9
leaq 0x130(%rdi), %r13
movq %rsi, %r15
movq %r12, %rsi
callq 0x1790
movq %r15, %rsi
movq %r13, %rdi
testb %al, %al
je 0x19be
movl $0x138, %edx            # imm = 0x138
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
callq 0x1070
movq %rbx, %rax
jmp 0x213d
movq 0x8(%rsp), %r14
cmpw $0x0, 0x2(%r14)
je 0x1b37
movq %r14, %r15
leaq 0x30(%rsp), %r14
movl $0x130, %r13d           # imm = 0x130
movl $0x130, %edx            # imm = 0x130
movq %r14, %rdi
movq %rsi, 0x28(%rsp)
movq %r12, %rsi
callq 0x1070
imulq $0x130, %rbx, %rsi      # imm = 0x130
addq %rbp, %rsi
movq %rbp, %rdi
movq %r14, %rdx
callq 0x2527
subq %rbp, %rax
cqto
idivq %r13
movzwl (%r15), %ecx
leal -0x1(%rcx), %edx
cmpl %ecx, %eax
cmovll %eax, %edx
movslq %edx, %rbx
imulq $0x130, %rbx, %rsi      # imm = 0x130
addq %rbp, %rsi
movq %r12, %rdi
callq 0x179e
leal 0x1(%rbx), %ecx
movslq %ecx, %rcx
testb %al, %al
cmovneq %rbx, %rcx
movslq 0xe44(%r15,%rcx,4), %rbp
movl $0x1000, %edi           # imm = 0x1000
callq 0x10a0
movq %rax, %r14
andl $0x0, (%rax)
movq %rbp, %rsi
shlq $0xc, %rsi
movq 0x18(%rsp), %r13
movq %r13, %rdi
xorl %edx, %edx
callq 0x10c0
pushq $0x1
popq %rdx
movl $0x1000, %esi           # imm = 0x1000
movq %r14, %rdi
movq %r13, %rcx
callq 0x10f0
leaq 0x30(%rsp), %rbx
movq %rbx, %rdi
movq 0x28(%rsp), %r15
movq %r15, %rsi
movq %r12, %rdx
movq %r14, %rcx
movl %ebp, %r8d
movq %r13, %r9
callq 0x1988
movl $0x1000, %esi           # imm = 0x1000
movq %r14, %rdi
callq 0x10b0
cmpb $0x1, (%rbx)
jne 0x1d95
movq 0x8(%rsp), %r14
cmpw $0xb, (%r14)
ja 0x1c6d
leaq 0x34(%rsp), %rsi
movq %r14, %rdi
callq 0x17ca
incl %eax
movzwl 0x2(%r14), %ecx
movl %ecx, %edx
movzwl %dx, %esi
cmpl %esi, %eax
jae 0x1d6c
leal -0x1(%rsi), %edx
movl 0xe44(%r14,%rdx,4), %edi
movl %esi, %esi
movl %edi, 0xe44(%r14,%rsi,4)
jmp 0x1b15
cmpw $0xb, %bx
ja 0x1b74
movq %r14, %rdi
movq %r14, %rbx
movq %rsi, %r14
movq %r12, %rsi
callq 0x17ca
movq %rbx, %rdi
movl 0x14(%rsp), %esi
movq 0x18(%rsp), %rdx
callq 0x2488
movl $0x138, %edx            # imm = 0x138
movq 0x20(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
jmp 0x19ec
movl $0xe78, %edi            # imm = 0xE78
callq 0x10a0
movq %rax, %r13
andw $0x0, 0x2(%rax)
leaq 0x5f4(%r14), %rsi
leaq 0x30(%rsp), %r15
movl $0x130, %edx            # imm = 0x130
movq %r15, %rdi
callq 0x1070
leaq 0x724(%r14), %rbp
movq %r14, %rbx
leaq 0x3c8(%rsp), %r14
movl $0x130, %edx            # imm = 0x130
movq %r14, %rdi
movq %rbp, %rsi
callq 0x1070
movw $0x6, %ax
movw %ax, (%rbx)
movw %ax, (%r13)
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0x24bd
testb %al, %al
je 0x1e90
movzbl %al, %eax
cmpl $0x1, %eax
je 0x1daf
cmpl $0xff, %eax
jne 0x1e2e
leaq 0x16c(%rsp), %rdi
leaq 0x30(%rsp), %r14
movl $0x12c, %edx            # imm = 0x12C
movq %r14, %rsi
callq 0x1070
movl 0x12c(%r14), %ebx
movq 0x8(%rsp), %rdi
decw (%rdi)
movq %r12, %rsi
callq 0x17ca
movq %r13, %r14
addq $0x4, %r14
xorl %r12d, %r12d
cmpq $0x720, %r12            # imm = 0x720
je 0x1e2e
leaq (%r12,%rbp), %rsi
leaq (%r14,%r12), %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movl 0x12c(%rbp,%r12), %eax
movl %eax, 0x12c(%r14,%r12)
addq $0x130, %r12            # imm = 0x130
jmp 0x1c35
movl $0x1000, %edi           # imm = 0x1000
callq 0x10a0
movq %rax, %r12
leaq 0x5f4(%r14), %rsi
leaq 0x3c8(%rsp), %rbx
movl $0x130, %edx            # imm = 0x130
movq %rbx, %rdi
callq 0x1070
leaq 0x724(%r14), %rsi
movq %r14, %r15
leaq 0x16c(%rsp), %r14
movl $0x130, %edx            # imm = 0x130
movq %r14, %rdi
callq 0x1070
movw $0x6, %ax
movw %ax, (%r15)
movw %ax, (%r12)
movw $0x7, %ax
movw %ax, 0x2(%r15)
movw %ax, 0x2(%r12)
leaq 0x34(%rsp), %r13
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x24bd
testb %al, %al
je 0x1fd3
movzbl %al, %eax
cmpl $0x1, %eax
movq 0x8(%rsp), %r14
je 0x1eef
cmpl $0xff, %eax
jne 0x20df
leaq 0x29c(%rsp), %rdi
leaq 0x3c8(%rsp), %rbx
movl $0x12c, %edx            # imm = 0x12C
movq %rbx, %rsi
callq 0x1070
movl 0x12c(%rbx), %ebp
decw (%r14)
movzwl 0x2(%r14), %eax
movl 0xe40(%r14,%rax,4), %r15d
movq %r14, %rdi
movq %r13, %rsi
callq 0x17ca
incl %eax
movzwl 0x2(%r14), %ecx
decq %rcx
cmpq %rax, %rcx
jle 0x2065
movl 0xe40(%r14,%rcx,4), %edx
movl %edx, 0xe44(%r14,%rcx,4)
jmp 0x1d4e
movl 0x164(%rsp), %edx
movl %eax, %eax
movl %edx, 0xe44(%r14,%rax,4)
incl %ecx
movw %cx, 0x2(%r14)
movq %r14, %rdi
movl 0x14(%rsp), %esi
movq 0x18(%rsp), %rdx
callq 0x2488
movl $0x138, %edx            # imm = 0x138
movq 0x20(%rsp), %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x1070
jmp 0x213a
leaq 0x16c(%rsp), %rdi
leaq 0x3c8(%rsp), %r14
movl $0x12c, %edx            # imm = 0x12C
movq %r14, %rsi
callq 0x1070
movl 0x12c(%r14), %ebx
movw $0x5, (%r13)
movq 0x8(%rsp), %rax
leaq 0x854(%rax), %r14
xorl %ebp, %ebp
cmpq $0x5f0, %rbp            # imm = 0x5F0
je 0x1e23
leaq (%r14,%rbp), %rsi
leaq 0x4(,%rbp), %rdi
addq %r13, %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movl 0x12c(%r14,%rbp), %eax
movl %eax, 0x130(%r13,%rbp)
addq $0x130, %rbp            # imm = 0x130
jmp 0x1de8
movq %r13, %rdi
movq %r12, %rsi
callq 0x17ca
movq 0x8(%rsp), %rdi
movl 0x14(%rsp), %esi
movq 0x18(%rsp), %r14
movq %r14, %rdx
callq 0x2488
movq %r13, %rdi
movq %r14, %rsi
callq 0x24e7
movl %eax, %ebp
movl $0xe78, %esi            # imm = 0xE78
movq %r13, %rdi
callq 0x10b0
movq 0x20(%rsp), %r14
movb $0x1, (%r14)
movl %ebp, 0x134(%r14)
leaq 0x4(%r14), %rdi
leaq 0x16c(%rsp), %rsi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movl %ebx, 0x130(%r14)
jmp 0x213a
leaq 0x16c(%rsp), %rdi
movl $0x12c, %edx            # imm = 0x12C
movq %r12, %rsi
callq 0x1070
movl 0x12c(%r12), %ebx
movq %r13, %r14
addq $0x4, %r14
xorl %r12d, %r12d
cmpq $0x720, %r12            # imm = 0x720
je 0x1e2e
leaq (%r12,%rbp), %rsi
leaq (%r14,%r12), %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movl 0x12c(%rbp,%r12), %eax
movl %eax, 0x12c(%r14,%r12)
addq $0x130, %r12            # imm = 0x130
jmp 0x1eb7
leaq 0x29c(%rsp), %rdi
leaq 0x16c(%rsp), %rbx
movl $0x12c, %edx            # imm = 0x12C
movq %rbx, %rsi
callq 0x1070
movl 0x12c(%rbx), %eax
movl %eax, 0x28(%rsp)
movw $0x5, (%r12)
movl $0x391, %r14d           # imm = 0x391
movl $0x215, %ebp            # imm = 0x215
movq 0x8(%rsp), %r15
cmpq $0x396, %r14            # imm = 0x396
je 0x1f72
leaq (%r15,%rbp,4), %rbx
leaq (%r12,%rbp,4), %rdi
addq $-0x850, %rdi           # imm = 0xF7B0
movl $0x12c, %edx            # imm = 0x12C
movq %rbx, %rsi
callq 0x1070
movl 0x12c(%rbx), %eax
movl %eax, -0x724(%r12,%rbp,4)
movl 0x1c(%r15,%r14,4), %eax
movl %eax, (%r12,%r14,4)
incq %r14
addq $0x4c, %rbp
jmp 0x1f2d
movq 0x8(%rsp), %r14
movl 0xe74(%r14), %eax
movl %eax, 0xe58(%r12)
movq %r12, %rdi
movq %r13, %rsi
callq 0x17ca
incl %eax
movzwl 0x2(%r12), %ecx
decl %ecx
movl 0x28(%rsp), %ebp
movzwl %cx, %edx
cmpl %edx, %eax
jae 0x1fbd
leal -0x1(%rdx), %ecx
movl 0xe44(%r12,%rcx,4), %esi
movl %edx, %edx
movl %esi, 0xe44(%r12,%rdx,4)
jmp 0x1f9f
movl 0x164(%rsp), %ecx
movl %eax, %eax
movl %ecx, 0xe44(%r12,%rax,4)
jmp 0x20df
leaq 0x29c(%rsp), %rdi
movl $0x12c, %edx            # imm = 0x12C
movq %r13, %rsi
callq 0x1070
movl 0x160(%rsp), %ebp
movq 0x8(%rsp), %rax
leaq 0x850(%rax), %rbx
movl $0x398, %r14d           # imm = 0x398
xorl %r13d, %r13d
cmpq $0x720, %r13            # imm = 0x720
je 0x2054
leaq (%rbx,%r13), %rsi
addq $-0x12c, %rsi           # imm = 0xFED4
leaq (%r12,%r13), %rdi
addq $0x4, %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movq 0x8(%rsp), %rcx
movl 0x850(%rcx,%r13), %eax
movl %eax, 0x130(%r12,%r13)
movl (%rcx,%r14,4), %eax
movl %eax, -0x18(%r12,%r14,4)
addq $0x130, %r13            # imm = 0x130
incq %r14
jmp 0x2004
movl 0x164(%rsp), %eax
movl %eax, 0xe44(%r12)
jmp 0x20da
movl 0x164(%rsp), %ecx
movl %ecx, 0xe44(%r14,%rax,4)
addq $0x850, %r14            # imm = 0x850
movl $0x398, %r13d           # imm = 0x398
xorl %ebx, %ebx
cmpq $0x720, %rbx            # imm = 0x720
je 0x20d2
leaq (%r14,%rbx), %rsi
addq $-0x12c, %rsi           # imm = 0xFED4
leaq (%r12,%rbx), %rdi
addq $0x4, %rdi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movq 0x8(%rsp), %rcx
movl 0x850(%rcx,%rbx), %eax
movl %eax, 0x130(%r12,%rbx)
movl (%rcx,%r13,4), %eax
movl %eax, -0x18(%r12,%r13,4)
addq $0x130, %rbx            # imm = 0x130
incq %r13
jmp 0x2083
movl %r15d, 0xe44(%r12)
movq 0x8(%rsp), %r14
movq %r14, %rdi
movl 0x14(%rsp), %esi
movq 0x18(%rsp), %rbx
movq %rbx, %rdx
callq 0x2488
movq %r12, %rdi
movq %rbx, %rsi
callq 0x24e7
movl %eax, %ebx
movl $0x1000, %esi           # imm = 0x1000
movq %r12, %rdi
callq 0x10b0
movq 0x20(%rsp), %r14
movb $0x1, (%r14)
movl %ebx, 0x134(%r14)
leaq 0x4(%r14), %rdi
leaq 0x29c(%rsp), %rsi
movl $0x12c, %edx            # imm = 0x12C
callq 0x1070
movl %ebp, 0x130(%r14)
movq %r14, %rax
addq $0x4f8, %rsp            # imm = 0x4F8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop