// File: /workspace/github_cpp_makefile_star2_O1/ksherlock[P]wdc-utils/expression.cpp
// Function: binary_op(unsigned int, std::vector<expr, std::allocator<expr>>&)
bool binary_op(unsigned op, std::vector<expr> &v) {
	if (v.size() >= 2) {
		expr &a = v[v.size() - 2];
		expr &b = v[v.size() - 1];

		if (a.tag == OP_VAL && b.tag == OP_VAL) {
			uint32_t value = 0;
			switch(op) {
			case OP_EXP: value = power(a.value, b.value); break;
			case OP_MUL: value = a.value * b.value; break;
			case OP_DIV: value = a.value / b.value; break;
			case OP_MOD: value = a.value % b.value; break;
			case OP_SHR: value = a.value >> b.value; break;
			case OP_SHL: value = a.value << b.value; break;
			case OP_ADD: value = a.value + b.value; break;
			case OP_SUB: value = a.value - b.value; break;
			case OP_AND: value = a.value & b.value; break;
			case OP_OR: value = a.value | b.value; break;
			case OP_XOR: value = a.value ^ b.value; break;
			case OP_EQ: value = a.value == b.value; break;
			case OP_GT: value = (int32_t)a.value > (int32_t)b.value; break;
			case OP_LT: value = (int32_t)a.value < (int32_t)b.value; break;
			case OP_UGT: value = a.value > b.value; break;
			case OP_ULT: value = a.value < b.value; break;
			default:
				errx(EX_SOFTWARE, "Unsupported binary op %02x", a.tag);
			}
			v.pop_back();
			v.back().value = value;
			return true;
		}
		if (a.tag == OP_VAL && b.tag == OP_LOC) {
			switch(op) {
				case OP_ADD: {
					// constant + symbol
					expr tmp = b;
					tmp.value = a.value + b.value;
					v.pop_back();
					v.pop_back();
					v.emplace_back(tmp);
					return true; 
				}
				#if 0
				case OP_SUB: {
					// constant - symbol .. does this even make sense?
					expr tmp = b;
					tmp.value = a.value - b.value;
					v.pop_back();
					v.pop_back();
					v.emplace_back(tmp);
					return true; 
				}
				#endif
			}
		}
		// optimization... regardless of where it's located, shifting > 24 bits will result in 0...
		if (a.tag == OP_LOC && b.tag == OP_VAL) {
			switch(op) {
				case OP_ADD: {
					a.value += b.value;
					v.pop_back();
					return true;
				}
				case OP_SUB: {
					a.value -= b.value;
					v.pop_back();
					return true;
				}
			}
		}

		if (a.tag == OP_LOC && b.tag == OP_LOC && a.section == b.section) {
			uint32_t value = 0;
			bool rv = false;
			switch (op) {
				case OP_SUB:
					// end - start
					value = a.value - b.value;
					rv = true; break;
				case OP_EQ:
					value = a.value == b.value;
					rv = true; break;
				case OP_GT:
				case OP_UGT:
					value = a.value > b.value;
					rv = true; break;
				case OP_LT:
				case OP_ULT:
					value = a.value < b.value;
					rv = true; break;
			}
			if (rv) {
				v.pop_back();
				v.pop_back();
				v.emplace_back(OP_VAL, value);
				return true;
			}
		}


	}
	v.emplace_back(op);
	return false;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rsi, %rbx
movl %edi, 0xc(%rsp)
movq (%rsi), %rcx
movq 0x8(%rsi), %rsi
movq %rsi, %r8
subq %rcx, %r8
movq %r8, %rax
sarq $0x2, %rax
movabsq $-0x5555555555555555, %r12 # imm = 0xAAAAAAAAAAAAAAAB
imulq %r12, %rax
cmpq $0x2, %rax
jb 0xb875
movl -0x18(%rcx,%r8), %eax
movl -0xc(%rcx,%r8), %edx
movl %eax, %r10d
xorl $0x2, %r10d
movl %edx, %r9d
xorl $0x2, %r9d
orl %r9d, %r10d
jne 0xb7ba
addl $-0x14, %edi
cmpl $0xf, %edi
ja 0xbaf3
leaq 0x41c9(%rip), %rax      # 0xf938
movslq (%rax,%rdi,4), %rdx
addq %rax, %rdx
jmpq *%rdx
leaq (%rcx,%r8), %rax
movl -0x8(%rax), %edx
testl %edx, %edx
je 0xb9a8
movl -0x14(%rcx,%r8), %ecx
movl $0x1, %edi
movl $0x1, %eax
movl %edx, %r8d
testb $0x1, %dl
movl %ecx, %r9d
cmovel %edi, %r9d
imull %r9d, %eax
imull %ecx, %ecx
shrl %r8d
cmpl $0x2, %edx
movl %r8d, %edx
jae 0xb799
jmp 0xb9ad
cmpl $0x2, %eax
jne 0xb813
cmpl $0x1a, %edi
jne 0xb813
cmpl $0x3, %edx
jne 0xb813
leaq (%rcx,%r8), %rax
addq $-0xc, %rax
movl 0x8(%rax), %ecx
movl %ecx, 0x8(%rsp)
movq (%rax), %rcx
movq %rcx, (%rsp)
movl 0x4(%rax), %ecx
addl -0x8(%rax), %ecx
movl %ecx, 0x4(%rsp)
addq $-0x18, %rsi
movq %rsi, 0x8(%rbx)
cmpq 0x10(%rbx), %rsi
je 0xb898
movl 0x8(%rsp), %eax
movl %eax, 0x8(%rsi)
movq (%rsp), %rax
movq %rax, (%rsi)
addq $0xc, 0x8(%rbx)
jmp 0xb9ff
xorl $0x3, %eax
orl %eax, %r9d
jne 0xb834
cmpl $0x1b, %edi
je 0xb889
cmpl $0x1a, %edi
jne 0xb834
movl -0x8(%rcx,%r8), %eax
addl %eax, -0x14(%rcx,%r8)
jmp 0xb9f7
xorl $0x3, %edx
orl %edx, %eax
jne 0xb875
movl -0x10(%rcx,%r8), %eax
cmpl -0x4(%rcx,%r8), %eax
jne 0xb875
addl $-0x1b, %edi
cmpl $0x8, %edi
ja 0xb875
leaq 0x40be(%rip), %rax      # 0xf914
movslq (%rax,%rdi,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movl -0x14(%rcx,%r8), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx,%r8), %eax
seta %r14b
jmp 0xb9d7
leaq 0xc(%rsp), %rsi
movq %rbx, %rdi
callq 0xbe64
xorl %eax, %eax
jmp 0xba01
movl -0x8(%rcx,%r8), %eax
subl %eax, -0x14(%rcx,%r8)
jmp 0xb9f7
movq %rsp, %rdx
movq %rbx, %rdi
callq 0xbfb6
jmp 0xb9ff
movl -0x14(%rcx,%r8), %edx
xorl %eax, %eax
cmpl -0x8(%rcx,%r8), %edx
seta %al
jmp 0xb9ad
movl -0x14(%rcx,%r8), %edx
xorl %eax, %eax
cmpl -0x8(%rcx,%r8), %edx
sete %al
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
movb -0x8(%rcx,%r8), %cl
shrl %cl, %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %edx
xorl %eax, %eax
cmpl -0x8(%rcx,%r8), %edx
setg %al
jmp 0xb9ad
movl -0x8(%rcx,%r8), %eax
orl -0x14(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
xorl %edx, %edx
divl -0x8(%rcx,%r8)
jmp 0xb9ad
movl -0x14(%rcx,%r8), %edx
xorl %eax, %eax
cmpl -0x8(%rcx,%r8), %edx
setb %al
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
xorl %edx, %edx
divl -0x8(%rcx,%r8)
movl %edx, %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
subl -0x8(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x8(%rcx,%r8), %eax
imull -0x14(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
movb -0x8(%rcx,%r8), %cl
shll %cl, %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %edx
xorl %eax, %eax
cmpl -0x8(%rcx,%r8), %edx
setl %al
jmp 0xb9ad
movl -0x8(%rcx,%r8), %eax
addl -0x14(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x8(%rcx,%r8), %eax
xorl -0x14(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x8(%rcx,%r8), %eax
andl -0x14(%rcx,%r8), %eax
jmp 0xb9ad
movl -0x14(%rcx,%r8), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx,%r8), %eax
setb %r14b
jmp 0xb9d7
movl $0x1, %eax
leaq -0xc(%rsi), %rcx
movq %rcx, 0x8(%rbx)
movl %eax, -0x14(%rsi)
jmp 0xb9ff
movl -0x14(%rcx,%r8), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx,%r8), %eax
sete %r14b
jmp 0xb9d7
movl -0x14(%rcx,%r8), %r14d
subl -0x8(%rcx,%r8), %r14d
leaq -0x18(%rsi), %r13
movq %r13, 0x8(%rbx)
cmpq 0x10(%rbx), %r13
je 0xba10
movl $0x2, -0x18(%rsi)
movl %r14d, -0x14(%rsi)
movl $0x0, -0x10(%rsi)
addq $-0xc, %rsi
movq %rsi, 0x8(%rbx)
movb $0x1, %al
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x3e10(%rip), %rdx      # 0xf827
movl $0x1, %esi
movq %rbx, %rdi
callq 0x9512
movq (%rbx), %rdi
movq 0x8(%rbx), %rbp
movq %r13, %r15
subq %rdi, %r15
sarq $0x2, %r15
imulq %r12, %r15
testq %rax, %rax
movq %rax, 0x10(%rsp)
je 0xba5b
movq %rdi, %r12
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x88c4
movq %r12, %rdi
movq %rax, %r12
jmp 0xba5e
xorl %r12d, %r12d
leaq (%r15,%r15,2), %rax
movl $0x2, (%r12,%rax,4)
movl %r14d, 0x4(%r12,%rax,4)
movl $0x0, 0x8(%r12,%rax,4)
movq %r12, %r14
cmpq %r13, %rdi
je 0xbaa0
movq %r12, %r14
movq %rdi, %rax
movl 0x8(%rax), %ecx
movl %ecx, 0x8(%r14)
movq (%rax), %rcx
movq %rcx, (%r14)
addq $0xc, %rax
addq $0xc, %r14
cmpq %r13, %rax
jne 0xba86
addq $0xc, %r14
cmpq %r13, %rbp
je 0xbac5
movl 0x8(%r13), %eax
movl %eax, 0x8(%r14)
movq (%r13), %rax
movq %rax, (%r14)
addq $0xc, %r13
addq $0xc, %r14
cmpq %rbp, %r13
jne 0xbaa9
testq %rdi, %rdi
je 0xbad6
movq 0x10(%rbx), %rsi
subq %rdi, %rsi
callq 0x2260
movq %r12, (%rbx)
movq %r14, 0x8(%rbx)
movq 0x10(%rsp), %rax
leaq (%rax,%rax,2), %rax
leaq (%r12,%rax,4), %rax
movq %rax, 0x10(%rbx)
jmp 0xb9ff
leaq 0x3e98(%rip), %rsi      # 0xf992
movl $0x46, %edi
movl $0x2, %edx
xorl %eax, %eax
callq 0x2430