// File: SYZYGYfpga[P]syzygy-tools/smartvio/syzygy.c
// Function: szgSolveSmartVIOGroup
int
szgSolveSmartVIOGroup(szgSmartVIOPort *ports, int group_mask)
{
	int i;
	int vmin, vmax;
	int fmin, fmax;
	int rangePtrs[SVIO_NUM_PORTS];


	for (i=0; i<SVIO_NUM_PORTS; rangePtrs[i++]=0);

	while (1) {
		// Prior to each intervals test, start with the least restrictive interval.
		// As we inspect the port settings, this interval will shrink.
		fmin = 0;
		fmax = 500;

		for (i=0; i<SVIO_NUM_PORTS; i++) {
			if (0 == ports[i].present) {
				continue;
			}

			// If the port group membership belongs to the group dependents, then this port
			// must factor into our SmartVIO solution. Otherwise, we skip it.
			if (0 == (group_mask & (1 << ports[i].group)) ) {
				continue;
			}

			// Check the minimum support version of the peripheral in the target port
			if ((ports[i].req_ver_major > SVIO_IMPL_VER_MAJOR)) {
				return -1;
			} else if ((ports[i].req_ver_major == SVIO_IMPL_VER_MAJOR)
			        && (ports[i].req_ver_minor > SVIO_IMPL_VER_MINOR)) {
				return -1;
			}

			// Check if a TXR2 or TXR4 peripheral is connected to the wrong port
			if ((ports[i].port_attr ^ ports[i].attr) & SZG_ATTR_TXR4) {
				return -1;
			}

			// Check the interval pointed to by rangePtr.
			vmin = ports[i].ranges[rangePtrs[i]].min;
			vmax = ports[i].ranges[rangePtrs[i]].max;
			if ((vmin == 0) && (vmax == 0)) {
				continue;
			}

			// If the intervals overlap, constrain the solution interval [fmin,fmax].
			// Otherwise, we declare no match.
			if ((fmin <= vmax) && (vmin <= fmax)) {
				fmin = szgMAX(fmin, vmin);
				fmax = szgMIN(fmax, vmax);
			} else {
				fmin = 0;
				break;
			}
		}
		if (fmin != 0) {
			return(fmin);
		}

		// Move to the next interval combination.
		for (i=0; i<SVIO_NUM_PORTS; i++) {
			rangePtrs[i]++;
			if (rangePtrs[i] >= ports[i].range_count) {
				rangePtrs[i] = 0;
			} else {
				break;
			}
		}
		// If the loop reaches the end, we've run through all combinations.
		// And alas, we haven't found a match.
		if (SVIO_NUM_PORTS == i) {
			fmin = 0;
			break;
		}
	}
	return(-1);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
cmpl $0x6, -0x18(%rbp)
jge 0x14531
jmp 0x1451a
movl -0x18(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0x18(%rbp)
cltq
movl $0x0, -0x40(%rbp,%rax,4)
jmp 0x14512
jmp 0x14533
movl $0x0, -0x24(%rbp)
movl $0x1f4, -0x28(%rbp)     # imm = 0x1F4
movl $0x0, -0x18(%rbp)
cmpl $0x6, -0x18(%rbp)
jge 0x146dc
movq -0x10(%rbp), %rcx
movslq -0x18(%rbp), %rax
imulq $0x6c, %rax, %rax
addq %rax, %rcx
xorl %eax, %eax
cmpl 0x4(%rcx), %eax
jne 0x1456d
jmp 0x146ce
movl -0x14(%rbp), %eax
movl %eax, -0x44(%rbp)
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
movl 0x8(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
movl -0x44(%rbp), %ecx
andl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
jne 0x1459c
jmp 0x146ce
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
cmpl $0x1, 0xc(%rax)
jbe 0x145bd
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1475e
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
cmpl $0x1, 0xc(%rax)
jne 0x145f3
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
cmpl $0x1, 0x10(%rax)
jbe 0x145f3
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1475e
jmp 0x145f5
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
movq -0x10(%rbp), %rcx
movslq -0x18(%rbp), %rdx
imulq $0x6c, %rdx, %rdx
addq %rdx, %rcx
xorl 0x14(%rcx), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0x1462d
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x1475e
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
movslq -0x18(%rbp), %rcx
movslq -0x40(%rbp,%rcx,4), %rcx
movl 0x24(%rax,%rcx,8), %eax
movl %eax, -0x1c(%rbp)
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
imulq $0x6c, %rcx, %rcx
addq %rcx, %rax
movslq -0x18(%rbp), %rcx
movslq -0x40(%rbp,%rcx,4), %rcx
movl 0x28(%rax,%rcx,8), %eax
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0x14679
cmpl $0x0, -0x20(%rbp)
jne 0x14679
jmp 0x146ce
movl -0x24(%rbp), %eax
cmpl -0x20(%rbp), %eax
jg 0x146c3
movl -0x1c(%rbp), %eax
cmpl -0x28(%rbp), %eax
jg 0x146c3
movl -0x24(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jle 0x14699
movl -0x24(%rbp), %eax
movl %eax, -0x48(%rbp)
jmp 0x1469f
movl -0x1c(%rbp), %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x24(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x146b5
movl -0x28(%rbp), %eax
movl %eax, -0x4c(%rbp)
jmp 0x146bb
movl -0x20(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0x146cc
movl $0x0, -0x24(%rbp)
jmp 0x146dc
jmp 0x146ce
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x14548
cmpl $0x0, -0x24(%rbp)
je 0x146ea
movl -0x24(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x1475e
movl $0x0, -0x18(%rbp)
cmpl $0x6, -0x18(%rbp)
jge 0x1473f
movslq -0x18(%rbp), %rax
movl -0x40(%rbp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, -0x40(%rbp,%rax,4)
movslq -0x18(%rbp), %rax
movl -0x40(%rbp,%rax,4), %eax
movq -0x10(%rbp), %rcx
movslq -0x18(%rbp), %rdx
imulq $0x6c, %rdx, %rdx
addq %rdx, %rcx
cmpl 0x20(%rcx), %eax
jl 0x14730
movslq -0x18(%rbp), %rax
movl $0x0, -0x40(%rbp,%rax,4)
jmp 0x14732
jmp 0x1473f
jmp 0x14734
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x146f1
movl $0x6, %eax
cmpl -0x18(%rbp), %eax
jne 0x14752
movl $0x0, -0x24(%rbp)
jmp 0x14757
jmp 0x14533
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
popq %rbp
retq