// File: /workspace/github_cpp_makefile_star2_O3/ksabry[P]bfbrute/src/ProgramIterator.h
// Function: ProgramIterator<400ul, 32ul, 12ul, 32ul>::Execute(char const*, unsigned long)
bool Execute(const char* initialData, const uint_fast32_t initialDataSize)
	{
		// TODO: short-circuit unbalanced linear loop if beyond bounds and ends on nonzero

		lastExecutionSuccessful = false;
		lastExecutionMaxProgramIdx = 0;

		uint_fast32_t programIdx = 0;
		dataIdx = data_size / 2 + cache_data_size;
		//dataBoundLow = dataIdx;
		//dataBoundHigh = dataIdx + 1;
		
		memset(data, 0, data_size + 2 * cache_data_size);
		memcpy(data + dataIdx, initialData, initialDataSize);

		uint_fast32_t remainingJumps = MAX_JUMPS;
		while (remainingJumps--)
		{
			assert(programIdx < iteratorCount);
			auto iteratorData = iterators[programIdx].Data();
			bool isLinear = jumps[programIdx].nonzero == programIdx;

			// Technically may be incorrect if iterator size is greater than 256
			//if (isLinear && dataIdx + iteratorData.idx < dataBoundLow && 
			//	iteratorData.data[iteratorData.idx] != 0) return false;
			//if (isLinear && dataIdx + iteratorData.idx >= dataBoundHigh &&
			//	iteratorData.data[iteratorData.idx] != 0) return false;
			//dataBoundLow = Min(dataBoundLow, dataIdx + iteratorData.start);
			//dataBoundHigh = Max(dataBoundHigh, dataIdx + iteratorData.end);

			if (isLinear && iterators[programIdx].IsBalanced())
			{
				uint8_t centerCell = iteratorData.data[iteratorData.idx + cache_data_size / 2];
				int cnt = divisionTable->Get(data[dataIdx], centerCell);
				if (cnt == -1)
				{
					return false;
				}

#ifdef SHORT_CIRCUIT_LINEAR_SINGULAR
				auto programSize = iteratorSizes[programIdx];
				if (programSize == centerCell || programSize == 256 - centerCell)
				{
					data[dataIdx] = 0; 
				}
				else ApplyDataMult(iteratorData, cnt);
#else
				ApplyDataMult(iteratorData.data, cnt);
#endif
				programIdx = jumps[programIdx].zero;
				continue;
			}

			uint_fast32_t newDataIdx = dataIdx + iteratorData.idx;
			if (newDataIdx < cache_data_size || newDataIdx >= data_size + cache_data_size)
			{
				return false;
			}
			
			ApplyData(iteratorData);
		
			dataIdx = newDataIdx;
			if (programIdx == iteratorCount - 1)
			{
				lastExecutionSuccessful = true;
				return true;
			}

			// TODO: test zero, nonzero in array
			programIdx = (data[dataIdx] == 0) ? jumps[programIdx].zero : jumps[programIdx].nonzero;
			if (programIdx > lastExecutionMaxProgramIdx)
			{
				lastExecutionMaxProgramIdx = programIdx;
			}
		}
		return false;
	}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x40, %rsp
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
movb $0x0, 0x4468(%rdi)
movq $0x0, 0x4470(%rdi)
movq $0xe8, 0x4448(%rdi)
leaq 0x4278(%rdi), %r14
xorl %r13d, %r13d
movl $0x1d0, %edx            # imm = 0x1D0
movq %r14, %rdi
xorl %esi, %esi
callq 0x2100
leaq 0x4360(%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2190
leaq 0x128(%rbx), %rcx
leaq 0x4030(%rbx), %rdx
movl $0xc34f, %esi           # imm = 0xC34F
movq %rsp, %rdi
movq 0x20(%rbx), %r9
cmpq %r9, %r13
jae 0x75f2
imulq $0x1e8, %r13, %rax      # imm = 0x1E8
movq 0x68(%rcx,%rax), %r8
movq %r8, 0x30(%rsp)
movups 0x38(%rcx,%rax), %xmm0
movups 0x48(%rcx,%rax), %xmm1
movups 0x58(%rcx,%rax), %xmm2
movaps %xmm2, 0x20(%rsp)
movaps %xmm1, 0x10(%rsp)
movaps %xmm0, (%rsp)
movq %r13, %r10
shlq $0x4, %r10
leaq (%rdx,%r10), %r8
cmpq %r13, 0x8(%rdx,%r10)
jne 0x7541
addq %rcx, %rax
cmpq $0x0, 0x58(%rax)
movq 0x4448(%rbx), %rax
jne 0x7548
movq 0x20(%rsp), %r9
movzbl 0x10(%r9,%rdi), %r10d
movzbl 0x4278(%rbx,%rax), %r9d
shll $0xa, %r9d
addq 0x4460(%rbx), %r9
movl (%r9,%r10,4), %r9d
cmpl $-0x1, %r9d
je 0x75d7
movq 0x28(%rbx,%r13,8), %r11
cmpq %r10, %r11
je 0x75c5
movl $0x100, %r15d           # imm = 0x100
subq %r10, %r15
cmpq %r15, %r11
je 0x75c5
movq 0x28(%rsp), %r10
movq 0x30(%rsp), %r11
cmpq %r11, %r10
jge 0x75ca
movb 0x10(%rsp,%r10), %al
mulb %r9b
movq 0x4448(%rbx), %r15
addq %r14, %r15
addb %al, (%r10,%r15)
incq %r10
cmpq %r10, %r11
jne 0x751e
jmp 0x75ca
movq 0x4448(%rbx), %rax
movq 0x20(%rsp), %r10
leaq (%r10,%rax), %r11
addq $-0x1b0, %r11           # imm = 0xFE50
cmpq $-0x190, %r11           # imm = 0xFE70
jb 0x75d7
movq 0x28(%rsp), %r11
movq 0x30(%rsp), %r15
cmpq %r15, %r11
jge 0x758f
movb 0x10(%rsp,%r11), %r9b
movq 0x4448(%rbx), %r12
addq %r14, %r12
addb %r9b, (%r11,%r12)
incq %r11
cmpq %r11, %r15
jne 0x7570
movq 0x20(%rbx), %r9
addq %rax, %r10
movq %r10, 0x4448(%rbx)
decq %r9
cmpq %r9, %r13
je 0x75db
xorl %eax, %eax
cmpb $0x0, 0x4278(%rbx,%r10)
setne %al
movq (%r8,%rax,8), %r13
cmpq 0x4470(%rbx), %r13
jbe 0x75cd
movq %r13, 0x4470(%rbx)
jmp 0x75cd
movb $0x0, (%r14,%rax)
movq (%r8), %r13
subq $0x1, %rsi
jae 0x7458
xorl %eax, %eax
jmp 0x75e4
movb $0x1, 0x4468(%rbx)
movb $0x1, %al
addq $0x40, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x20f9(%rip), %rdi      # 0x96f2
leaq 0x1c59(%rip), %rsi      # 0x9259
leaq 0x2106(%rip), %rcx      # 0x970d
movl $0x211, %edx            # imm = 0x211
callq 0x2120
nop