// File: /workspace/github_c_makefile_star2_O0/Nico01[P]obj2asm/t_tree.c
// Function: insert
NODE_T *insert(void *data, NODE_T *root_node, int (*cmp_routine)(const void *, const void *))
{
    NODE_T *insert_node;
    NODE_T *curr_node; /* Current node we are visiting      */
    NODE_T *son_node;
    NODE_T *grand_son;
    NODE_T *path[32]; /* 32 levels (2^32 records!) */
    int direct[32];
    int level;
    int curr_direct;
    int con_direct;

    /* Prepare initial value for tree traversal */
    level = 0;
    son_node = root_node;

    /*
    **  Traverse tree looking for the place to insert this new node.  If
    **  we find a node which gives a comparison result of 0 (equal), then
    **  we cannot insert this new node.  To indicate this duplicate value,
    **  a pointer to the node which contains the duplicate value is returned.
    */
    do {
        curr_node = son_node; /* Advance to new son_node */

        /*  Compare this new node with the node at this position in the
            tree and determine which direction to proceed from here.
        */
        curr_direct = (*cmp_routine)(curr_node->data, data);

        /*  is this node is a duplicate node?
         */
        if (curr_direct == EQUAL) {
            if (root_node->balance == LEFT) { /* Duplicates allowed? */
                curr_direct = LEFT;           /* see new_tree()!!!!  */
            }
            else {
                return (curr_node);
            }
        }

        path[level] = curr_node;
        direct[level] = curr_direct;
        level++;

        son_node = curr_node->ptr[curr_direct];

    } while (!curr_node->thread[curr_direct]);

    /*  Now, we have found the place to insert this node,
        make the last visited node point to this new node.
    */
    con_direct = 1 - curr_direct;

    /* Set up default values for this node which we are going to insert */
    insert_node = (NODE_T *)o_malloc(sizeof(NODE_T));

    insert_node->data = data;
    insert_node->balance = BALANCED;
    insert_node->thread[curr_direct] = TRUE;
    insert_node->thread[con_direct] = TRUE;
    insert_node->ptr[curr_direct] = curr_node->ptr[curr_direct];
    insert_node->ptr[con_direct] = curr_node;

    curr_node->thread[curr_direct] = FALSE;
    curr_node->ptr[curr_direct] = insert_node;

    /*  Now loop through 'un-stacking' the path which we took on our
        way to get this guy inserted.  Keep in mind that this process
        is done in stack-order, so the last node visited will be the
        first node processed, etc.  Also keep in mind that the loop
        may be terminated before back-tracking completely to the root
        node (ie. the entire path is not processed).
    */
    do {
        son_node = curr_node;

        level--;

        /*  If we have gotten back out to the root of the tree,
            then the height of the tree has increase.
        */
        if (level == 0) { /* Increment depth (see new_tree()!!!) */
            root_node->ptr[LEFT] = (NODE_T *)(((int)root_node->ptr[LEFT]) + 1);
            break;
        }

        /*  Get path information at this stack level
         */
        curr_node = path[level];
        curr_direct = direct[level];

        /*  If the node at this position along the path was BALANCED,
            then make it lean in the direction we took from it on our
            way down.
        */
        if (curr_node->balance == BALANCED) {
            curr_node->balance = curr_direct;
        }
        else {
            /*  Otherwise, two cases may arise.
                1.  The node was unbalanced in the opposite
                    direction to the direction we took.
                    (In this case that node will become balanced)
            */
            if (curr_node->balance != curr_direct) {
                curr_node->balance = BALANCED;
                break;
            }
            else {
                /* or 2.  The node was already unbalanced in the same
                          direction we took. If this happens we may need to
                          do single or double rotation.  Single rotation
                          happens if the node (which is in the opposite
                          direction to the direction we took) is leaning
                          the direction we took (from the current node).
                          Otherwise to double rotation.
                */
                con_direct = 1 - curr_direct;
                if (son_node->balance == curr_direct) {
                    swap(son_node, con_direct, curr_node, curr_direct);
                    curr_node->balance = BALANCED;
                }
                else {
                    grand_son = son_node->ptr[con_direct];
                    swap(grand_son, curr_direct, son_node, con_direct);
                    swap(grand_son, con_direct, curr_node, curr_direct);
                    son_node->balance = (grand_son->balance == con_direct) ? curr_direct : BALANCED;
                    curr_node->balance = (grand_son->balance == curr_direct) ? con_direct : BALANCED;
                    son_node = grand_son;
                }
                son_node->balance = BALANCED;

                /* now make parent point to new rotated node */
                path[level - 1]->ptr[direct[level - 1]] = son_node;
                break;
            }
        }
    } while (TRUE);

    /*  Return a pointer to the node inserted */
    return (insert_node);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1e0, %rsp            # imm = 0x1E0
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl $0x0, -0x1c4(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq -0x30(%rbp), %rcx
movq 0x20(%rcx), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
movl %eax, -0x1c8(%rbp)
cmpl $0x2, -0x1c8(%rbp)
jne 0x16899
movq -0x18(%rbp), %rax
movswl (%rax), %eax
cmpl $0x0, %eax
jne 0x1688a
movl $0x0, -0x1c8(%rbp)
jmp 0x16897
movq -0x30(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x16baf
jmp 0x16899
movq -0x30(%rbp), %rcx
movslq -0x1c4(%rbp), %rax
movq %rcx, -0x140(%rbp,%rax,8)
movl -0x1c8(%rbp), %ecx
movslq -0x1c4(%rbp), %rax
movl %ecx, -0x1c0(%rbp,%rax,4)
movl -0x1c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c4(%rbp)
movq -0x30(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
cmpl $0x0, 0x18(%rax,%rcx,4)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x16849
movl $0x1, %eax
subl -0x1c8(%rbp), %eax
movl %eax, -0x1cc(%rbp)
movl $0x28, %edi
callq 0x16e40
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, 0x20(%rax)
movq -0x28(%rbp), %rax
movw $0x2, (%rax)
movq -0x28(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movl $0x1, 0x18(%rax,%rcx,4)
movq -0x28(%rbp), %rax
movslq -0x1cc(%rbp), %rcx
movl $0x1, 0x18(%rax,%rcx,4)
movq -0x30(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rdx
movq -0x28(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movq -0x30(%rbp), %rdx
movq -0x28(%rbp), %rax
movslq -0x1cc(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movq -0x30(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movl $0x0, 0x18(%rax,%rcx,4)
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rax
movslq -0x1c8(%rbp), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
movq -0x30(%rbp), %rax
movq %rax, -0x38(%rbp)
movl -0x1c4(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x1c4(%rbp)
cmpl $0x0, -0x1c4(%rbp)
jne 0x169f0
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
addl $0x1, %eax
movslq %eax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x16ba7
movslq -0x1c4(%rbp), %rax
movq -0x140(%rbp,%rax,8), %rax
movq %rax, -0x30(%rbp)
movslq -0x1c4(%rbp), %rax
movl -0x1c0(%rbp,%rax,4), %eax
movl %eax, -0x1c8(%rbp)
movq -0x30(%rbp), %rax
movswl (%rax), %eax
cmpl $0x2, %eax
jne 0x16a38
movl -0x1c8(%rbp), %eax
movw %ax, %cx
movq -0x30(%rbp), %rax
movw %cx, (%rax)
jmp 0x16b99
movq -0x30(%rbp), %rax
movswl (%rax), %eax
cmpl -0x1c8(%rbp), %eax
je 0x16a55
movq -0x30(%rbp), %rax
movw $0x2, (%rax)
jmp 0x16ba7
movl $0x1, %eax
subl -0x1c8(%rbp), %eax
movl %eax, -0x1cc(%rbp)
movq -0x38(%rbp), %rax
movswl (%rax), %eax
cmpl -0x1c8(%rbp), %eax
jne 0x16a9c
movq -0x38(%rbp), %rdi
movl -0x1cc(%rbp), %esi
movq -0x30(%rbp), %rdx
movl -0x1c8(%rbp), %ecx
callq 0x16bc0
movq -0x30(%rbp), %rax
movw $0x2, (%rax)
jmp 0x16b5e
movq -0x38(%rbp), %rax
movslq -0x1cc(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rdi
movl -0x1c8(%rbp), %esi
movq -0x38(%rbp), %rdx
movl -0x1cc(%rbp), %ecx
callq 0x16bc0
movq -0x40(%rbp), %rdi
movl -0x1cc(%rbp), %esi
movq -0x30(%rbp), %rdx
movl -0x1c8(%rbp), %ecx
callq 0x16bc0
movq -0x40(%rbp), %rax
movswl (%rax), %eax
cmpl -0x1cc(%rbp), %eax
jne 0x16aff
movl -0x1c8(%rbp), %eax
movl %eax, -0x1d0(%rbp)
jmp 0x16b0c
movl $0x2, %eax
movl %eax, -0x1d0(%rbp)
jmp 0x16b0c
movl -0x1d0(%rbp), %eax
movw %ax, %cx
movq -0x38(%rbp), %rax
movw %cx, (%rax)
movq -0x40(%rbp), %rax
movswl (%rax), %eax
cmpl -0x1c8(%rbp), %eax
jne 0x16b39
movl -0x1cc(%rbp), %eax
movl %eax, -0x1d4(%rbp)
jmp 0x16b46
movl $0x2, %eax
movl %eax, -0x1d4(%rbp)
jmp 0x16b46
movl -0x1d4(%rbp), %eax
movw %ax, %cx
movq -0x30(%rbp), %rax
movw %cx, (%rax)
movq -0x40(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movw $0x2, (%rax)
movq -0x38(%rbp), %rdx
movl -0x1c4(%rbp), %eax
subl $0x1, %eax
cltq
movq -0x140(%rbp,%rax,8), %rax
movl -0x1c4(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movslq -0x1c0(%rbp,%rcx,4), %rcx
movq %rdx, 0x8(%rax,%rcx,8)
jmp 0x16ba7
jmp 0x16b9b
movb $0x1, %al
testb $0x1, %al
jne 0x169b5
jmp 0x16ba7
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x1e0, %rsp            # imm = 0x1E0
popq %rbp
retq
nopl (%rax)