// File: /workspace/github_cpp_makefile_star2_O1/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, 0x20(%rsp)
movl %r8d, 0x8(%rsp)
movq %rcx, 0x18(%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, 0x14(%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 0x292e6
testb %al, %al
je 0x2967d
movslq %r13d, %rax
imulq $0x560, %rax, %rcx      # imm = 0x560
leaq (%rbx,%rcx), %rsi
addq $0x40, %rsi
movl 0x98(%rsi), %ecx
cmpl $0x7, %ecx
jg 0x2967d
movslq 0x98(%rsi), %rcx
leal 0x1(%rcx), %edx
movl %edx, 0x98(%rsi)
imulq $0x98, %rcx, %rcx
movq %rbp, %rdx
leaq (%rsi,%rcx), %rbp
addq $0xa0, %rbp
movq 0x90(%rsi), %rcx
movq %rcx, (%rbp)
movl %r13d, 0x20(%rbp)
movb $0x0, 0x74(%rbp)
movl %r15d, 0x10(%rbp)
movl %r14d, 0x24(%rbp)
movq 0x18(%rsp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x68(%rbp)
movl 0x8(%rsp), %ecx
movl %ecx, 0x18(%rbp)
movb %r12b, 0x14(%rbp)
movq 0x20(%rsp), %rcx
movl (%rcx), %ecx
movl %ecx, 0x6c(%rbp)
movq 0x28(%rsp), %rcx
movq %rcx, 0x28(%rbp)
movl 0x14(%rsp), %ecx
movl %ecx, 0x70(%rbp)
movq %rdx, 0x8(%rsp)
movq %rdx, 0x8(%rbp)
movq $0x0, 0x60(%rbp)
movq 0x30(%rsp), %rcx
movq %rcx, 0x30(%rbp)
movslq 0x34(%rbx), %rcx
testq %rcx, %rcx
jle 0x29555
xorl %edx, %edx
movb $0x0, 0x75(%rbp,%rdx)
incq %rdx
cmpq %rdx, %rcx
jne 0x29548
movq %rsi, %r14
movq %rbp, 0x90(%rsi)
testl %ecx, %ecx
jle 0x295c8
cmpl $0x2, 0x2c(%rbx)
jl 0x295c8
leaq 0xc8(%rbx), %rdx
movl $0x1, %esi
xorl %edi, %edi
cmpq %rdi, %r13
je 0x295b4
movl (%rdx), %r8d
cmpl $0x2, %r8d
jne 0x295b4
movslq 0x10(%rdx), %r8
testq %r8, %r8
je 0x295a3
imulq $0x98, %r8, %r8
addq %rax, %r8
movb -0xb(%rdx,%r8), %r8b
cmpb $0x1, %r8b
jne 0x295b4
movl $0x3, (%rdx)
movq %rbp, 0x8(%rdx)
movb $0x1, 0x75(%rbp,%rdi)
incl %esi
incq %rdi
cmpq %rcx, %rdi
jae 0x295c8
addq $0x560, %rdx            # imm = 0x560
cmpl 0x2c(%rbx), %esi
jl 0x29577
movq %rbx, %rdi
callq 0x52e0
cmpl $0x0, 0x34(%rbx)
jle 0x2962a
leaq 0x70(%rbx), %r15
xorl %r12d, %r12d
cmpq %r12, %r13
je 0x295eb
movb 0x75(%rbp,%r12), %al
cmpb $0x1, %al
jne 0x29617
movl $0x4, 0x58(%r15)
cmpq %r12, %r13
je 0x29617
cmpb $0x0, 0x30(%rbx)
je 0x29617
movq %r15, %rdi
callq 0x55f0
leaq 0x28(%r15), %rdi
callq 0x5030
movq %r15, %rdi
callq 0x52e0
incq %r12
movslq 0x34(%rbx), %rax
addq $0x560, %r15            # imm = 0x560
cmpq %rax, %r12
jl 0x295dd
movq %rbx, %rdi
movl %r13d, %esi
movq %rbp, %rdx
callq 0x24ae0
movq %rbx, %rdi
callq 0x55f0
movl 0x68(%rbp), %eax
movq 0x18(%rsp), %rcx
movl %eax, (%rcx)
movl 0x6c(%rbp), %eax
movq 0x20(%rsp), %rcx
movl %eax, (%rcx)
decl 0x98(%r14)
movq (%rbp), %rax
movq %rax, 0x90(%r14)
movq 0x8(%rsp), %r14
movq 0x1930(%r14), %rax
addq 0x60(%rbp), %rax
movq %rax, 0x1930(%r14)
movq %rbx, %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x52e0
nop