// File: /workspace/github_cpp_makefile_star2_O3/ATOMIC-LICHESS[P]ATOMKRAFT/thread.cpp
// Function: void ThreadsManager::split<false>(Position&, SearchStack*, Value*, Value, Value*, Depth, Move, int, MovePicker*, bool)
void ThreadsManager::split(Position& pos, SearchStack* ss, Value* alpha, const Value beta,
                           Value* bestValue, Depth depth, Move threatMove,
                           int moveCount, MovePicker* mp, bool pvNode) {
  assert(pos.is_ok());
  assert(*bestValue >= -VALUE_INFINITE);
  assert(*bestValue <= *alpha);
  assert(*alpha < beta);
  assert(beta <= VALUE_INFINITE);
  assert(depth > DEPTH_ZERO);
  assert(pos.thread() >= 0 && pos.thread() < activeThreads);
  assert(activeThreads > 1);

  int i, master = pos.thread();
  Thread& masterThread = threads[master];

  lock_grab(&mpLock);

  // If no other thread is available to help us, or if we have too many
  // active split points, don't split.
  if (   !available_slave_exists(master)
      || masterThread.activeSplitPoints >= MAX_ACTIVE_SPLIT_POINTS)
  {
      lock_release(&mpLock);
      return;
  }

  // Pick the next available split point object from the split point stack
  SplitPoint& splitPoint = masterThread.splitPoints[masterThread.activeSplitPoints++];

  // Initialize the split point object
  splitPoint.parent = masterThread.splitPoint;
  splitPoint.master = master;
  splitPoint.is_betaCutoff = false;
  splitPoint.depth = depth;
  splitPoint.threatMove = threatMove;
  splitPoint.alpha = *alpha;
  splitPoint.beta = beta;
  splitPoint.pvNode = pvNode;
  splitPoint.bestValue = *bestValue;
  splitPoint.mp = mp;
  splitPoint.moveCount = moveCount;
  splitPoint.pos = &pos;
  splitPoint.nodes = 0;
  splitPoint.ss = ss;
  for (i = 0; i < activeThreads; i++)
      splitPoint.is_slave[i] = false;

  masterThread.splitPoint = &splitPoint;

  // If we are here it means we are not available
  assert(masterThread.state != Thread::AVAILABLE);

  int workersCnt = 1; // At least the master is included

  // Allocate available threads setting state to THREAD_BOOKED
  for (i = 0; !Fake && i < activeThreads && workersCnt < maxThreadsPerSplitPoint; i++)
      if (i != master && threads[i].is_available_to(master))
      {
          threads[i].state = Thread::BOOKED;
          threads[i].splitPoint = &splitPoint;
          splitPoint.is_slave[i] = true;
          workersCnt++;
      }

  assert(Fake || workersCnt > 1);

  // We can release the lock because slave threads are already booked and master is not available
  lock_release(&mpLock);

  // Tell the threads that they have work to do. This will make them leave
  // their idle loop.
  for (i = 0; i < activeThreads; i++)
      if (i == master || splitPoint.is_slave[i])
      {
          assert(i == master || threads[i].state == Thread::BOOKED);

          threads[i].state = Thread::WORKISWAITING; // This makes the slave to exit from idle_loop()

          if (useSleepingThreads && i != master)
              threads[i].wake_up();
      }

  // Everything is set up. The master thread enters the idle loop, from
  // which it will instantly launch a search, because its state is
  // THREAD_WORKISWAITING.  We send the split point as a second parameter to the
  // idle loop, which means that the main thread will return from the idle
  // loop when all threads have finished their work at this split point.
  idle_loop(master, &splitPoint);

  // We have returned from the idle loop, which means that all threads are
  // finished. Update alpha and bestValue, and return.
  lock_grab(&mpLock);

  *alpha = splitPoint.alpha;
  *bestValue = splitPoint.bestValue;
  masterThread.activeSplitPoints--;
  masterThread.splitPoint = splitPoint.parent;
  pos.set_nodes_searched(pos.nodes_searched() + splitPoint.nodes);

  lock_release(&mpLock);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r9, 0x18(%rsp)
movl %r8d, (%rsp)
movq %rcx, 0x10(%rsp)
movq %rdx, 0x30(%rsp)
movq %rsi, %rbp
movq %rdi, %rbx
movq 0x88(%rsp), %rax
movq %rax, 0x28(%rsp)
movl 0x80(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0x78(%rsp), %r14d
movl 0x70(%rsp), %r15d
movb 0x90(%rsp), %r12b
movl 0x192c(%rsi), %r13d
callq 0x55f0
movq %rbx, %rdi
movl %r13d, %esi
callq 0x2962a
testb %al, %al
je 0x29a04
movslq %r13d, %rax
imulq $0x560, %rax, %rcx      # imm = 0x560
leaq (%rbx,%rcx), %rdi
addq $0x40, %rdi
movl 0x98(%rdi), %ecx
cmpl $0x7, %ecx
jg 0x29a04
movslq 0x98(%rdi), %rcx
leal 0x1(%rcx), %edx
movl %edx, 0x98(%rdi)
imulq $0x98, %rcx, %rcx
movq %rbp, %rdx
leaq (%rdi,%rcx), %rbp
addq $0xa0, %rbp
movq 0x90(%rdi), %rcx
movq %rcx, (%rbp)
movl %r13d, 0x20(%rbp)
movb $0x0, 0x74(%rbp)
movl %r15d, 0x10(%rbp)
movl %r14d, 0x24(%rbp)
movq 0x10(%rsp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x68(%rbp)
movl (%rsp), %ecx
movl %ecx, 0x18(%rbp)
movb %r12b, 0x14(%rbp)
movq 0x18(%rsp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x6c(%rbp)
movq 0x28(%rsp), %rcx
movq %rcx, 0x28(%rbp)
movl 0xc(%rsp), %ecx
movl %ecx, 0x70(%rbp)
movq %rdx, (%rsp)
movq %rdx, 0x8(%rbp)
movq $0x0, 0x60(%rbp)
movq 0x30(%rsp), %rcx
movq %rcx, 0x30(%rbp)
movslq 0x34(%rbx), %rcx
testq %rcx, %rcx
movq %rdi, 0x20(%rsp)
jle 0x29926
xorl %edx, %edx
movb $0x0, 0x75(%rbp,%rdx)
incq %rdx
cmpq %rdx, %rcx
jne 0x29894
testl %ecx, %ecx
setg %sil
movq %rbp, 0x90(%rdi)
movl 0x2c(%rbx), %edx
cmpl $0x2, %edx
setge %dil
andb %sil, %dil
cmpb $0x1, %dil
jne 0x2992d
leaq 0xc8(%rbx), %rsi
movl $0x1, %edi
xorl %r8d, %r8d
cmpq %r8, %r13
je 0x29911
movl (%rsi), %r9d
cmpl $0x2, %r9d
jne 0x29911
movslq 0x10(%rsi), %r9
testq %r9, %r9
je 0x298fc
imulq $0x98, %r9, %r9
addq %rax, %r9
movb -0xb(%rsi,%r9), %r9b
cmpb $0x1, %r9b
jne 0x29911
movl $0x3, (%rsi)
movq %rbp, 0x8(%rsi)
movb $0x1, 0x75(%rbp,%r8)
incl %edi
movl 0x2c(%rbx), %edx
incq %r8
cmpq %rcx, %r8
jae 0x2992d
addq $0x560, %rsi            # imm = 0x560
cmpl %edx, %edi
jl 0x298d0
jmp 0x2992d
movq %rbp, 0x90(%rdi)
movq %rbx, %rdi
callq 0x52e0
movl 0x34(%rbx), %eax
testl %eax, %eax
jle 0x299ae
leaq 0x40(%rbx), %rcx
imulq $0x560, %r13, %rdx      # imm = 0x560
leaq (%rcx,%rdx), %r12
addq $0x88, %r12
leaq 0x70(%rbx), %r15
xorl %r14d, %r14d
cmpq %r14, %r13
jne 0x29968
movl $0x4, (%r12)
jmp 0x2999c
movb 0x75(%rbp,%r14), %cl
cmpb $0x1, %cl
jne 0x2999c
movl $0x4, 0x58(%r15)
cmpb $0x1, 0x30(%rbx)
jne 0x2999c
movq %r15, %rdi
callq 0x55f0
leaq 0x28(%r15), %rdi
callq 0x5030
movq %r15, %rdi
callq 0x52e0
movl 0x34(%rbx), %eax
incq %r14
movslq %eax, %rcx
addq $0x560, %r15            # imm = 0x560
cmpq %rcx, %r14
jl 0x29959
movq %rbx, %rdi
movl %r13d, %esi
movq %rbp, %rdx
callq 0x24f6e
movq %rbx, %rdi
callq 0x55f0
movl 0x68(%rbp), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
movl 0x6c(%rbp), %eax
movq 0x18(%rsp), %rcx
movl %eax, (%rcx)
movq 0x20(%rsp), %rcx
decl 0x98(%rcx)
movq (%rbp), %rax
movq %rax, 0x90(%rcx)
movq (%rsp), %rcx
movq 0x1930(%rcx), %rax
addq 0x60(%rbp), %rax
movq %rax, 0x1930(%rcx)
movq %rbx, %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x52e0