// File: /workspace/github_cpp_makefile_star2_O2/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, 0x28(%rsp)
movl %r8d, 0x8(%rsp)
movq %rcx, 0x20(%rsp)
movq %rdx, (%rsp)
movq %rsi, %rbp
movq %rdi, %rbx
movq 0x88(%rsp), %rax
movq %rax, 0x30(%rsp)
movl 0x80(%rsp), %eax
movl %eax, 0x14(%rsp)
movl 0x78(%rsp), %r14d
movl 0x70(%rsp), %r13d
movb 0x90(%rsp), %r12b
movslq 0x192c(%rsi), %r15
callq 0x55d0
movq %rbx, %rdi
movl %r15d, %esi
callq 0x21fa4
testb %al, %al
je 0x22316
imulq $0x560, %r15, %rax      # imm = 0x560
leaq (%rbx,%rax), %rdx
addq $0x40, %rdx
movl 0x98(%rdx), %eax
cmpl $0x7, %eax
jg 0x22316
movslq 0x98(%rdx), %rax
leal 0x1(%rax), %ecx
movl %ecx, 0x98(%rdx)
imulq $0x98, %rax, %rax
movq %rbp, %rcx
leaq (%rdx,%rax), %rbp
addq $0xa0, %rbp
movq %rdx, 0x18(%rsp)
movq 0x90(%rdx), %rax
movq %rax, (%rbp)
movl %r15d, 0x20(%rbp)
movb $0x0, 0x74(%rbp)
movl %r13d, 0x10(%rbp)
movl %r14d, 0x24(%rbp)
movq 0x20(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x68(%rbp)
movl 0x8(%rsp), %eax
movl %eax, 0x18(%rbp)
movb %r12b, 0x14(%rbp)
movq 0x28(%rsp), %rax
movl (%rax), %eax
movl %eax, 0x6c(%rbp)
movl %r15d, %r12d
movq 0x30(%rsp), %rax
movq %rax, 0x28(%rbp)
movl 0x14(%rsp), %eax
movl %eax, 0x70(%rbp)
movq %rcx, 0x8(%rsp)
movq %rcx, 0x8(%rbp)
movq $0x0, 0x60(%rbp)
movq (%rsp), %rax
movq %rax, 0x30(%rbp)
movl 0x34(%rbx), %eax
movslq %eax, %rcx
xorl %edx, %edx
cmpq %rcx, %rdx
jge 0x22203
movb $0x0, 0x75(%rbp,%rdx)
incq %rdx
jmp 0x221f4
movq %r15, (%rsp)
movq 0x18(%rsp), %rcx
movq %rbp, 0x90(%rcx)
leaq 0xd0(%rbx), %r15
pushq $0x1
popq %r14
xorl %r13d, %r13d
cltq
cmpq %rax, %r13
jge 0x2226a
cmpl 0x2c(%rbx), %r14d
jge 0x2226a
cmpq %r13, %r12
je 0x2225b
leaq -0x90(%r15), %rdi
movq (%rsp), %rsi
callq 0x21c2e
testb %al, %al
je 0x2225b
movl $0x3, -0x8(%r15)
movq %rbp, (%r15)
movb $0x1, 0x75(%rbp,%r13)
incl %r14d
incq %r13
movl 0x34(%rbx), %eax
addq $0x560, %r15            # imm = 0x560
jmp 0x22221
movq %rbx, %rdi
callq 0x52d0
leaq 0xc8(%rbx), %r14
xorl %r15d, %r15d
movq 0x18(%rsp), %r13
movslq 0x34(%rbx), %rax
cmpq %rax, %r15
jge 0x222c2
cmpq %r15, %r12
je 0x22298
movb 0x75(%rbp,%r15), %al
cmpb $0x1, %al
jne 0x222b6
movl $0x4, (%r14)
cmpq %r15, %r12
je 0x222b6
cmpb $0x0, 0x30(%rbx)
je 0x222b6
leaq -0x88(%r14), %rdi
callq 0x21be2
incq %r15
addq $0x560, %r14            # imm = 0x560
jmp 0x22281
movq %rbx, %rdi
movq (%rsp), %rsi
movq %rbp, %rdx
callq 0x1dade
movq %rbx, %rdi
callq 0x55d0
movl 0x68(%rbp), %eax
movq 0x20(%rsp), %rcx
movl %eax, (%rcx)
movl 0x6c(%rbp), %eax
movq 0x28(%rsp), %rcx
movl %eax, (%rcx)
decl 0x98(%r13)
movq (%rbp), %rax
movq %rax, 0x90(%r13)
movq 0x8(%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 0x52d0