// File: /workspace/github_cpp_makefile_star2_O3/cpottamus[P]btree_lab/btree.cc
// Function: BTreeIndex::Rebalance(unsigned int const&, std::vector<unsigned int, std::allocator<unsigned int>>)
ERROR_T BTreeIndex::Rebalance(const SIZE_T &node, std::vector<SIZE_T> ptrPath)
{
  BTreeNode b;
  BTreeNode leftNode;
  BTreeNode rightNode;
  ERROR_T rc;
  SIZE_T offset;
    
  int newType;
  //SIZE_T ptr;
  rc = b.Unserialize(buffercache, node);
  if (rc) { return rc;}
  //std::cout<<":::: Allocating new Nodes :::::"<<std::endl;
  //Allocate 2 new nodes, fill them from the place you're splitting
  SIZE_T leftPtr;
  SIZE_T rightPtr;
  AllocateNode(leftPtr);
  if(b.info.nodetype == BTREE_LEAF_NODE){
    newType = BTREE_LEAF_NODE;
  }else{
    newType = BTREE_INTERIOR_NODE;
  }
  leftNode = BTreeNode(newType, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  rc = leftNode.Serialize(buffercache, leftPtr);
  AllocateNode(rightPtr);
  rightNode = BTreeNode(newType, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  rc = rightNode.Serialize(buffercache, rightPtr);
  //Unserialize to write to new nodes
  rc = leftNode.Unserialize(buffercache, leftPtr);
  if (rc) { return rc;}
  rc = rightNode.Unserialize(buffercache, rightPtr);
  if (rc) { return rc;}

  //Variables to hold spot/key vals  
  KEY_T keySpot;
  KEY_T testKey;
  VALUE_T valSpot;
  SIZE_T ptrSpot;

  //Find splitting point
  int midpoint = (b.info.numkeys+0.5)/2;

  //If A leafNode
  if(b.info.nodetype==BTREE_LEAF_NODE){
  //Build left leaf node, include the splitting key (this is a <= B+ tree)
    for(offset = 0; (int)offset < midpoint; offset++){
      //std::cout<<":::: OFFSET for building new left leaf node = "<<offset<<std::endl;
      leftNode.info.numkeys++;

    //Get old node values
      rc = b.GetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = b.GetVal(offset, valSpot);
      if (rc) { return rc;}
    //set values in new left node.
      rc = leftNode.SetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = leftNode.SetVal(offset, valSpot);
      if (rc) { return rc;}
    }
  //Build right leaf node
    int spot=0;
    for(offset = midpoint; offset<b.info.numkeys; offset++){
      //std::cout<<":::: OFFSET (spot) for building new right leaf node = "<<spot<<std::endl;
      //std::cout<<":::: Total Block OFFSET (offset), while rebuilding right leaf node"<<offset<<std::endl;
    //Get values from old node.
      rightNode.info.numkeys++;
      rc = b.GetKey(offset, keySpot);
      if (rc) { return rc;}
      rc = b.GetVal(offset, valSpot);
      if (rc) { return rc;}
    //set values in new right node.
      rc = rightNode.SetKey(spot, keySpot);
      if (rc) { return rc;}
      rc = rightNode.SetVal(spot, valSpot);
      if (rc) { return rc;}
      spot++;
    }
  } else {//if it's an interior node.
      //Build left interior node
  for(offset = 0; (int)offset < midpoint; offset++){
    //std::cout<<":::: OFFSET for building new left interior node = "<<offset<<std::endl;
    leftNode.info.numkeys++;
        //Get old key and pointers
    rc = b.GetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = b.GetPtr(offset, ptrSpot);
    if (rc) { return rc;}
        //Set new key and Pointer vals
    rc = leftNode.SetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = leftNode.SetPtr(offset, ptrSpot);
  }
      //Build Right interior node
  int spot=0;
  for(offset = midpoint; offset<b.info.numkeys; offset++){
    //std::cout<<":::: OFFSET (spot) for building new right interior node = "<<spot<<std::endl;
    //std::cout<<":::: Total Block OFFSET (offset), while rebuilding right interior node"<<offset<<std::endl;
    rightNode.info.numkeys++;
    //Get values from old node.
    rc = b.GetKey(offset, keySpot);
    if (rc) { return rc;}
    rc = b.GetPtr(offset, ptrSpot);
    if (rc) { return rc;}
    //set values in new right node.
    rc = rightNode.SetKey(spot, keySpot);
    if (rc) { return rc;}
    rc = rightNode.SetPtr(spot, ptrSpot);
    if (rc) { return rc;}
    spot++;
  }
  rc = b.GetPtr(offset, ptrSpot);
  if (rc) { return rc;}
  rc = rightNode.SetPtr(spot, ptrSpot);
  if (rc) { return rc;}
}
  //Serialize the new nodes
rc = leftNode.Serialize(buffercache, leftPtr);
if (rc) { return rc;}
rc = rightNode.Serialize(buffercache, rightPtr);
if (rc) { return rc;}
rc = b.Serialize(buffercache, node);

  //Find split key
KEY_T splitKey;
rc = b.GetKey(midpoint-1, splitKey);
if (rc) { return rc;}


  //If we're all the way up at the root, we need to make a new root.
  //  std::cout << ":::: NODE TYPE = " << b.info.nodetype << std::endl;
    
  //  std::cout<<"current node nodetype :::: "<<b.info.nodetype<<std::endl;
if (b.info.nodetype == BTREE_ROOT_NODE) {
  //std::cout<<":::: AT THE TOP, BUILDING A NEW ROOT ::::"<<std::endl;
  SIZE_T newRootPtr;
  BTreeNode newRootNode;
  AllocateNode(newRootPtr);
  newRootNode = BTreeNode(BTREE_ROOT_NODE, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
  superblock.info.rootnode = newRootPtr;
    newRootNode.info.rootnode = newRootPtr;
    newRootNode.info.numkeys = 1;
    newRootNode.SetKey(0, splitKey);
    newRootNode.SetPtr(0, leftPtr);
    newRootNode.SetPtr(1, rightPtr);
  rc = newRootNode.Serialize(buffercache, newRootPtr);
  if(rc) {return rc;}
//std::cout<<"::: We made it here! Root node"<<std::endl;
}
else{
//Find the parent node
  SIZE_T parentPtr = ptrPath.back();
//  std::cout<<"WE BUILT THIS CITY ON ROCK AND ROLL COW ::: "<<parentPtr<<std::endl;
      //std::cout<<"ALSO THIS  IN OUR REBALANCE::: "<<ptrPath.size()<<std::endl;
//    for(int i =ptrPath.size()-1; i>=0; i--) {
//        std::cout<<"Little sumpin"<<ptrPath.at(i)<<std::endl;
//      }
  ptrPath.pop_back();
  BTreeNode parentNode;
  rc = parentNode.Unserialize(buffercache, parentPtr);
  if(rc) {return rc;}

    if (parentNode.info.nodetype == BTREE_SUPERBLOCK) {
        AllocateNode(parentPtr);
        
    }
//Increment the key count for the given node.
  //parentNode.info.numkeys++;
    
    BTreeNode newParentNode = BTreeNode(parentNode.info.nodetype, superblock.info.keysize, superblock.info.valuesize, superblock.info.blocksize);
    newParentNode.info.numkeys = parentNode.info.numkeys + 1;
    newParentNode.info.freelist = parentNode.info.freelist;
    
    bool newKeyInserted = false;
    for (offset = 0; offset < newParentNode.info.numkeys - 1; offset++) {
        rc = parentNode.GetKey(offset, testKey);
        //    if(rc){ return rc;}
        if (newKeyInserted) {
            rc = parentNode.GetKey(offset, keySpot);
            newParentNode.SetKey(offset + 1, keySpot);
            
            rc = parentNode.GetPtr(offset + 1, ptrSpot);
            newParentNode.SetPtr(offset + 2, ptrSpot);
        } else {
            if (splitKey < testKey) {
                newKeyInserted = true;
                newParentNode.SetPtr(offset, leftPtr);
                newParentNode.SetKey(offset, splitKey);
                newParentNode.SetPtr(offset+1, rightPtr);
                offset = offset - 1;
                
            } else {
                rc = parentNode.GetKey(offset, keySpot);
                if (rc) {return rc;}
                rc = newParentNode.SetKey(offset, keySpot);
                if (rc) {return rc;}
                
                rc = parentNode.GetPtr(offset, ptrSpot);
                if (rc) {return rc;}
                rc = newParentNode.SetPtr(offset, ptrSpot);
                if (rc) {return rc;}
            }
        }
    }
    if (newKeyInserted == false) {
        newKeyInserted = true;
        newParentNode.SetPtr(offset, leftPtr);
        newParentNode.SetKey(offset, splitKey);
        newParentNode.SetPtr(offset+1, rightPtr);
    }
    
    newParentNode.Serialize(buffercache, parentPtr);
    
    
//find split keys spot in parent (interior) node, insert it and update keys and pointers.
//  for(offset = 0; offset<parentNode.info.numkeys-1; offset++){
//    //std::cout<<":::: Searching Interior Nodes for splitKey Insertion ::::: offset = "<<offset<<std::endl;
//    rc = parentNode.GetKey(offset, testKey);
//    if(rc){ return rc;}
//    if(splitKey < testKey || splitKey == testKey){ // if testkey > splitkey
//      //std::cout<<":::: Moving through the parent node for rebalance insertion ::: Number of keys in parent = "<<parentNode.info.numkeys<<std::endl;
//      //std::cout<<":::: Moving through the parent node for rebalance insertion ::: parent nodetype = "<<parentNode.info.nodetype<<std::endl;
//          //Once you've found the insertion point for the new key, move all other keys & pointers over by 1
//      for(offset2= parentNode.info.numkeys-2 ; offset2 >= offset; offset2-- ){
//        //std::cout<<":::: Found INSERTION POINT, moving spots over :::: = offset"<<offset<<std::endl;
//            //Grab the old key and pointer
//        rc = parentNode.GetKey(offset2, keySpot);
//        if(rc){ return rc;}
//        rc = parentNode.GetPtr(offset2, ptrSpot);
//        if(rc){ return rc;}
//            //Move it up by 1
//        rc = parentNode.SetKey(offset2+1, keySpot);
//        if(rc){ return rc;}
//        rc = parentNode.SetPtr(offset2+2, ptrSpot);
//      }
//          //We now have moved every pointer over except for the  1 to the immediate right of where we will be inserting our splitKey
//          //Set our pointers and our new key
//      rc = parentNode.SetPtr(offset2+1, rightPtr);
//      if(rc){ return rc;}
//      rc = parentNode.SetPtr(offset,leftPtr);
//      if(rc){ return rc;}
//      rc = parentNode.SetKey(offset, splitKey);
//      if(rc){ return rc;}
//
//      break;
//    }
//  }


  //Check the length of the node and call rebalance if necessary
  //parentNode.Serialize(buffercache, parentPtr);

  if((int)newParentNode.info.numkeys > (int)(2*maxNumKeys/3)){
    rc = Rebalance(parentPtr, ptrPath);
    if(rc){ return rc;}
  }
}
  //Deallocate the old (too large) node
DeallocateNode(node);
return ERROR_NOERROR;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdx, %r12
movq %rsi, %rbx
movq %rdi, %r14
leaq 0x78(%rsp), %rdi
callq 0x7c4a
leaq 0xf0(%rsp), %rdi
callq 0x7c4a
leaq 0xc8(%rsp), %rdi
callq 0x7c4a
movq 0x8(%r14), %rsi
movl (%rbx), %edx
leaq 0x78(%rsp), %rdi
callq 0x7e00
movl %eax, %ebp
testl %eax, %eax
jne 0x68ef
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0x560c
xorl %ebp, %ebp
cmpl $0x4, 0x78(%rsp)
sete %bpl
addl $0x3, %ebp
movl 0x1c(%r14), %edx
movl 0x20(%r14), %ecx
movl 0x24(%r14), %r8d
leaq 0x50(%rsp), %rdi
movl %ebp, %esi
callq 0x7c7c
leaq 0xf0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x7d2c
leaq 0x50(%rsp), %rdi
callq 0x7c5a
movq 0x8(%r14), %rsi
movl 0x10(%rsp), %edx
leaq 0xf0(%rsp), %rdi
callq 0x7d3a
leaq 0xc(%rsp), %rsi
movq %r14, %rdi
callq 0x560c
movl 0x1c(%r14), %edx
movl 0x20(%r14), %ecx
movl 0x24(%r14), %r8d
leaq 0x50(%rsp), %rdi
movl %ebp, %esi
callq 0x7c7c
leaq 0xc8(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x7d2c
leaq 0x50(%rsp), %rdi
callq 0x7c5a
movq 0x8(%r14), %rsi
movl 0xc(%rsp), %edx
leaq 0xc8(%rsp), %rdi
callq 0x7d3a
movq 0x8(%r14), %rsi
movl 0x10(%rsp), %edx
leaq 0xf0(%rsp), %rdi
callq 0x7e00
movl %eax, %ebp
testl %eax, %eax
jne 0x68ef
movq 0x8(%r14), %rsi
movl 0xc(%rsp), %edx
leaq 0xc8(%rsp), %rdi
callq 0x7e00
movl %eax, %ebp
testl %eax, %eax
jne 0x68ef
leaq 0x50(%rsp), %rdi
callq 0x2c58
leaq 0x180(%rsp), %rdi
callq 0x2c58
leaq 0x158(%rsp), %rdi
callq 0x2c58
movl 0x90(%rsp), %eax
cvtsi2sd %rax, %xmm0
movsd 0x3164(%rip), %xmm1     # 0x96a0
addsd %xmm1, %xmm0
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %r15d
cmpl $0x4, 0x78(%rsp)
movq %r15, 0x18(%rsp)
jne 0x66c5
testl %r15d, %r15d
jle 0x660e
movq %r12, 0x20(%rsp)
xorl %r13d, %r13d
leaq 0x78(%rsp), %r15
leaq 0x50(%rsp), %r12
incl 0x108(%rsp)
movq %r15, %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq %r15, %rdi
movl %r13d, %esi
leaq 0x158(%rsp), %rdx
callq 0x8096
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xf0(%rsp), %rdi
movl %r13d, %esi
movq %r12, %rdx
callq 0x8118
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xf0(%rsp), %rdi
movl %r13d, %esi
leaq 0x158(%rsp), %rdx
callq 0x816c
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
incl %r13d
cmpl %r13d, 0x18(%rsp)
jne 0x6574
movl 0x90(%rsp), %eax
movq 0x20(%rsp), %r12
movq 0x18(%rsp), %r15
cmpl %r15d, %eax
jbe 0x684d
xorl %r13d, %r13d
addl %r13d, %r15d
incl 0xe0(%rsp)
leaq 0x78(%rsp), %rdi
movl %r15d, %esi
leaq 0x50(%rsp), %rdx
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0x78(%rsp), %rdi
movl %r15d, %esi
leaq 0x158(%rsp), %rdx
callq 0x8096
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xc8(%rsp), %rdi
movl %r13d, %esi
leaq 0x50(%rsp), %rdx
callq 0x8118
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xc8(%rsp), %rdi
movl %r13d, %esi
leaq 0x158(%rsp), %rdx
callq 0x816c
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq 0x18(%rsp), %r15
leal (%r15,%r13), %eax
incl %eax
movl %r13d, %ecx
incl %ecx
movl %ecx, %r13d
cmpl 0x90(%rsp), %eax
jb 0x661a
jmp 0x684d
testl %r15d, %r15d
jle 0x6766
movq %r12, 0x20(%rsp)
xorl %r15d, %r15d
leaq 0x78(%rsp), %r12
leaq 0x50(%rsp), %r13
incl 0x108(%rsp)
movq %r12, %rdi
movl %r15d, %esi
movq %r13, %rdx
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq %r12, %rdi
movl %r15d, %esi
leaq 0x8(%rsp), %rdx
callq 0x8078
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xf0(%rsp), %rdi
movl %r15d, %esi
movq %r13, %rdx
callq 0x8118
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xf0(%rsp), %rdi
movl %r15d, %esi
leaq 0x8(%rsp), %rdx
callq 0x814e
incl %r15d
cmpl %r15d, 0x18(%rsp)
jne 0x66e0
movl 0x90(%rsp), %eax
movq 0x20(%rsp), %r12
movq 0x18(%rsp), %r15
xorl %r13d, %r13d
movl %r15d, %esi
cmpl %r15d, %eax
jbe 0x6819
xorl %r13d, %r13d
addl %r13d, %r15d
incl 0xe0(%rsp)
leaq 0x78(%rsp), %rdi
movl %r15d, %esi
leaq 0x50(%rsp), %rdx
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0x78(%rsp), %rdi
movl %r15d, %esi
leaq 0x8(%rsp), %rdx
callq 0x8078
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xc8(%rsp), %rdi
movl %r13d, %esi
leaq 0x50(%rsp), %rdx
callq 0x8118
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xc8(%rsp), %rdi
movl %r13d, %esi
leaq 0x8(%rsp), %rdx
callq 0x814e
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movl %r13d, %eax
incl %r13d
movq 0x18(%rsp), %r15
addl %r15d, %eax
incl %eax
cmpl 0x90(%rsp), %eax
jb 0x6778
leal (%r15,%r13), %esi
leaq 0x78(%rsp), %rdi
leaq 0x8(%rsp), %rdx
callq 0x8078
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
leaq 0xc8(%rsp), %rdi
leaq 0x8(%rsp), %rdx
movl %r13d, %esi
callq 0x814e
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq 0x8(%r14), %rsi
movl 0x10(%rsp), %edx
leaq 0xf0(%rsp), %rdi
callq 0x7d3a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq 0x8(%r14), %rsi
movl 0xc(%rsp), %edx
leaq 0xc8(%rsp), %rdi
callq 0x7d3a
movl %eax, %ebp
testl %eax, %eax
jne 0x68cb
movq 0x8(%r14), %rsi
movl (%rbx), %edx
leaq 0x78(%rsp), %rdi
callq 0x7d3a
leaq 0x130(%rsp), %rdi
callq 0x2c58
decl %r15d
leaq 0x78(%rsp), %rdi
leaq 0x130(%rsp), %rdx
movl %r15d, %esi
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
je 0x6927
leaq 0x130(%rsp), %rdi
callq 0x2e26
leaq 0x158(%rsp), %rdi
callq 0x2e26
leaq 0x180(%rsp), %rdi
callq 0x2e26
leaq 0x50(%rsp), %rdi
callq 0x2e26
leaq 0xc8(%rsp), %rdi
callq 0x7c5a
leaq 0xf0(%rsp), %rdi
callq 0x7c5a
leaq 0x78(%rsp), %rdi
callq 0x7c5a
movl %ebp, %eax
addq $0x1a8, %rsp            # imm = 0x1A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl $0x2, 0x78(%rsp)
jne 0x6a06
leaq 0xa0(%rsp), %rdi
callq 0x7c4a
leaq 0x14(%rsp), %rsi
movq %r14, %rdi
callq 0x560c
movl 0x1c(%r14), %edx
movl 0x20(%r14), %ecx
movl 0x24(%r14), %r8d
leaq 0x28(%rsp), %rdi
movl $0x2, %esi
callq 0x7c7c
leaq 0xa0(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x7d2c
leaq 0x28(%rsp), %rdi
callq 0x7c5a
movl 0x14(%rsp), %ebp
movl %ebp, 0x28(%r14)
leaq 0xa0(%rsp), %rdi
movl %ebp, 0x10(%rdi)
movl $0x1, 0x18(%rdi)
leaq 0x130(%rsp), %rdx
xorl %esi, %esi
callq 0x8118
leaq 0xa0(%rsp), %rdi
leaq 0x10(%rsp), %rdx
xorl %esi, %esi
callq 0x814e
leaq 0xa0(%rsp), %rdi
leaq 0xc(%rsp), %rdx
movl $0x1, %esi
callq 0x814e
movq 0x8(%r14), %rsi
leaq 0xa0(%rsp), %rdi
movl %ebp, %edx
callq 0x7d3a
movl %eax, %ebp
leaq 0xa0(%rsp), %rdi
callq 0x7c5a
testl %ebp, %ebp
jne 0x68be
jmp 0x6ce4
movq 0x8(%r12), %rax
movl -0x4(%rax), %ebp
addq $-0x4, %rax
movl %ebp, 0x14(%rsp)
movq %rax, 0x8(%r12)
leaq 0xa0(%rsp), %rdi
callq 0x7c4a
movq 0x8(%r14), %rsi
leaq 0xa0(%rsp), %rdi
movl %ebp, %edx
callq 0x7e00
movl %eax, %ebp
testl %eax, %eax
je 0x6a53
leaq 0xa0(%rsp), %rdi
callq 0x7c5a
jmp 0x68be
movl 0xa0(%rsp), %esi
cmpl $0x1, %esi
jne 0x6a73
leaq 0x14(%rsp), %rsi
movq %r14, %rdi
callq 0x560c
movl 0xa0(%rsp), %esi
movq %r12, 0x20(%rsp)
movl 0x1c(%r14), %edx
movl 0x20(%r14), %ecx
movl 0x24(%r14), %r8d
leaq 0x28(%rsp), %rdi
callq 0x7c7c
movl 0xb4(%rsp), %eax
movl 0xb8(%rsp), %ecx
leal 0x1(%rcx), %edx
movl %edx, 0x40(%rsp)
movl %eax, 0x3c(%rsp)
testl %ecx, %ecx
je 0x6c06
xorl %r15d, %r15d
leaq 0xa0(%rsp), %r13
xorl %r12d, %r12d
movq %r13, %rdi
movl %r12d, %esi
leaq 0x180(%rsp), %rdx
callq 0x802a
testb $0x1, %r15b
je 0x6b24
movq %r13, %rdi
movl %r12d, %esi
leaq 0x50(%rsp), %rdx
callq 0x802a
leal 0x1(%r12), %ebp
leaq 0x28(%rsp), %rdi
movl %ebp, %esi
leaq 0x50(%rsp), %rdx
callq 0x8118
movq %r13, %rdi
movl %ebp, %esi
leaq 0x8(%rsp), %rdx
callq 0x8078
leal 0x2(%r12), %esi
leaq 0x28(%rsp), %rdi
leaq 0x8(%rsp), %rdx
callq 0x814e
jmp 0x6bec
leaq 0x130(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x2e9e
testb %al, %al
je 0x6b80
leaq 0x28(%rsp), %rdi
movl %r12d, %esi
leaq 0x10(%rsp), %rdx
callq 0x814e
leaq 0x28(%rsp), %rdi
movl %r12d, %esi
leaq 0x130(%rsp), %rdx
callq 0x8118
leal 0x1(%r12), %esi
leaq 0x28(%rsp), %rdi
leaq 0xc(%rsp), %rdx
callq 0x814e
decl %r12d
movb $0x1, %r15b
jmp 0x6bec
movq %r13, %rdi
movl %r12d, %esi
leaq 0x50(%rsp), %rdx
callq 0x802a
movl %eax, %ebp
testl %eax, %eax
jne 0x6cba
leaq 0x28(%rsp), %rdi
movl %r12d, %esi
leaq 0x50(%rsp), %rdx
callq 0x8118
movl %eax, %ebp
testl %eax, %eax
jne 0x6cba
movq %r13, %rdi
movl %r12d, %esi
leaq 0x8(%rsp), %rdx
callq 0x8078
movl %eax, %ebp
testl %eax, %eax
jne 0x6cba
leaq 0x28(%rsp), %rdi
movl %r12d, %esi
leaq 0x8(%rsp), %rdx
callq 0x814e
movl %eax, %ebp
testl %eax, %eax
jne 0x6cba
incl %r12d
movl 0x40(%rsp), %eax
decl %eax
cmpl %eax, %r12d
jb 0x6abd
testb $0x1, %r15b
je 0x6c09
jmp 0x6c45
xorl %r12d, %r12d
leaq 0x28(%rsp), %rdi
leaq 0x10(%rsp), %rdx
movl %r12d, %esi
callq 0x814e
leaq 0x28(%rsp), %rdi
leaq 0x130(%rsp), %rdx
movl %r12d, %esi
callq 0x8118
incl %r12d
leaq 0x28(%rsp), %rdi
leaq 0xc(%rsp), %rdx
movl %r12d, %esi
callq 0x814e
movq 0x8(%r14), %rsi
movl 0x14(%rsp), %edx
leaq 0x28(%rsp), %rdi
callq 0x7d3a
movl 0x40(%r14), %eax
addl %eax, %eax
movl $0xaaaaaaab, %ecx       # imm = 0xAAAAAAAB
imulq %rax, %rcx
shrq $0x21, %rcx
cmpl %ecx, 0x40(%rsp)
jle 0x6cbf
leaq 0x118(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x7906
leaq 0x14(%rsp), %rsi
leaq 0x118(%rsp), %rdx
movq %r14, %rdi
callq 0x63b4
movl %eax, %ebp
movq 0x118(%rsp), %rdi
testq %rdi, %rdi
je 0x6cb6
movq 0x128(%rsp), %rsi
subq %rdi, %rsi
callq 0x21e0
testl %ebp, %ebp
je 0x6cbf
xorl %r15d, %r15d
jmp 0x6cc4
xorl %ebp, %ebp
movb $0x1, %r15b
leaq 0x28(%rsp), %rdi
callq 0x7c5a
leaq 0xa0(%rsp), %rdi
callq 0x7c5a
testb %r15b, %r15b
je 0x68be
xorl %ebp, %ebp
movq %r14, %rdi
movq %rbx, %rsi
callq 0x56bc
jmp 0x68be
movq %rax, %rbx
movq 0x118(%rsp), %rdi
testq %rdi, %rdi
je 0x6d35
movq 0x128(%rsp), %rsi
subq %rdi, %rsi
callq 0x21e0
jmp 0x6d35
jmp 0x6d26
jmp 0x6d32
jmp 0x6d32
jmp 0x6d26
jmp 0x6d2d
jmp 0x6d2d
jmp 0x6d26
movq %rax, %rbx
jmp 0x6d3f
jmp 0x6d86
movq %rax, %rbx
jmp 0x6d4c
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x7c5a
leaq 0xa0(%rsp), %rdi
callq 0x7c5a
leaq 0x130(%rsp), %rdi
callq 0x2e26
jmp 0x6d89
jmp 0x6d86
jmp 0x6d86
movq %rax, %rbx
jmp 0x6d96
movq %rax, %rbx
jmp 0x6da3
jmp 0x6dbb
jmp 0x6d86
jmp 0x6d86
jmp 0x6d73
jmp 0x6dbb
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x7c5a
jmp 0x6dbe
jmp 0x6dbb
jmp 0x6d86
movq %rax, %rbx
leaq 0x158(%rsp), %rdi
callq 0x2e26
leaq 0x180(%rsp), %rdi
callq 0x2e26
leaq 0x50(%rsp), %rdi
callq 0x2e26
jmp 0x6dbe
jmp 0x6dbb
movq %rax, %rbx
jmp 0x6dcb
movq %rax, %rbx
jmp 0x6dd8
movq %rax, %rbx
leaq 0xc8(%rsp), %rdi
callq 0x7c5a
leaq 0xf0(%rsp), %rdi
callq 0x7c5a
leaq 0x78(%rsp), %rdi
callq 0x7c5a
movq %rbx, %rdi
callq 0x2370