// File: /workspace/github_cpp_makefile_star2_O3/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), %rax
movq 0x8(%rsi), %rsi
movq %rsi, %rdx
subq %rax, %rdx
movq %rdx, %rcx
sarq $0x2, %rcx
movabsq $-0x5555555555555555, %r12 # imm = 0xAAAAAAAAAAAAAAAB
imulq %r12, %rcx
cmpq $0x2, %rcx
jb 0xb68f
leaq (%rax,%rdx), %rcx
movl -0x18(%rax,%rdx), %r9d
movl -0xc(%rax,%rdx), %r8d
movl %r9d, %r11d
xorl $0x2, %r11d
movl %r8d, %r10d
xorl $0x2, %r10d
orl %r10d, %r11d
jne 0xb5d4
addl $-0x14, %edi
cmpl $0xf, %edi
ja 0xb8b4
leaq 0x43a9(%rip), %rax      # 0xf938
movslq (%rax,%rdi,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movl -0x8(%rcx), %edx
testl %edx, %edx
je 0xb760
movl -0x14(%rcx), %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 0xb5b3
jmp 0xb765
cmpl $0x2, %r9d
jne 0xb636
cmpl $0x1a, %edi
jne 0xb68f
cmpl $0x3, %r8d
jne 0xb68f
addq %rdx, %rax
addq $-0xc, %rax
movl 0x8(%rax), %edx
movl %edx, 0x8(%rsp)
movq (%rax), %rax
movq %rax, (%rsp)
movl -0x8(%rcx), %eax
addl -0x14(%rcx), %eax
movl %eax, 0x4(%rsp)
addq $-0x18, %rsi
movq %rsi, 0x8(%rbx)
cmpq 0x10(%rbx), %rsi
je 0xb6a3
movl 0x8(%rsp), %eax
movl %eax, 0x8(%rsi)
movq (%rsp), %rax
movq %rax, (%rsi)
addq $0xc, 0x8(%rbx)
jmp 0xb770
xorl $0x3, %r9d
orl %r9d, %r10d
jne 0xb654
cmpl $0x1b, %edi
je 0xb6b3
cmpl $0x1a, %edi
jne 0xb68f
movl -0x8(%rcx), %eax
addl %eax, -0x14(%rcx)
jmp 0xb7c7
xorl $0x3, %r8d
orl %r8d, %r9d
jne 0xb68f
movl -0x10(%rcx), %eax
cmpl -0x4(%rcx), %eax
jne 0xb68f
addl $-0x1b, %edi
cmpl $0x8, %edi
ja 0xb68f
leaq 0x42a0(%rip), %rax      # 0xf914
movslq (%rax,%rdi,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movl -0x14(%rcx), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx), %eax
seta %r14b
jmp 0xb7a7
leaq 0xc(%rsp), %rsi
movq %rbx, %rdi
callq 0xbc5e
xorl %eax, %eax
jmp 0xb772
movq %rsp, %rdx
movq %rbx, %rdi
callq 0xbdb2
jmp 0xb770
movl -0x8(%rcx), %eax
subl %eax, -0x14(%rcx)
jmp 0xb7c7
movl -0x14(%rcx), %edx
xorl %eax, %eax
cmpl -0x8(%rcx), %edx
seta %al
jmp 0xb765
movl -0x14(%rcx), %edx
xorl %eax, %eax
cmpl -0x8(%rcx), %edx
sete %al
jmp 0xb765
movl -0x14(%rcx), %eax
movb -0x8(%rcx), %cl
shrl %cl, %eax
jmp 0xb765
movl -0x14(%rcx), %edx
xorl %eax, %eax
cmpl -0x8(%rcx), %edx
setg %al
jmp 0xb765
movl -0x8(%rcx), %eax
orl -0x14(%rcx), %eax
jmp 0xb765
movl -0x14(%rcx), %eax
xorl %edx, %edx
divl -0x8(%rcx)
jmp 0xb765
movl -0x14(%rcx), %edx
xorl %eax, %eax
cmpl -0x8(%rcx), %edx
setb %al
jmp 0xb765
movl -0x14(%rcx), %eax
xorl %edx, %edx
divl -0x8(%rcx)
movl %edx, %eax
jmp 0xb765
movl -0x14(%rcx), %eax
subl -0x8(%rcx), %eax
jmp 0xb765
movl -0x8(%rcx), %eax
imull -0x14(%rcx), %eax
jmp 0xb765
movl -0x14(%rcx), %eax
movb -0x8(%rcx), %cl
shll %cl, %eax
jmp 0xb765
movl -0x14(%rcx), %edx
xorl %eax, %eax
cmpl -0x8(%rcx), %edx
setl %al
jmp 0xb765
movl -0x8(%rcx), %eax
addl -0x14(%rcx), %eax
jmp 0xb765
movl -0x8(%rcx), %eax
xorl -0x14(%rcx), %eax
jmp 0xb765
movl -0x8(%rcx), %eax
andl -0x14(%rcx), %eax
jmp 0xb765
movl $0x1, %eax
leaq -0xc(%rsi), %rcx
movq %rcx, 0x8(%rbx)
movl %eax, -0x14(%rsi)
movb $0x1, %al
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl -0x14(%rcx), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx), %eax
setb %r14b
jmp 0xb7a7
movl -0x14(%rcx), %eax
xorl %r14d, %r14d
cmpl -0x8(%rcx), %eax
sete %r14b
jmp 0xb7a7
movl -0x14(%rcx), %r14d
subl -0x8(%rcx), %r14d
leaq -0x18(%rsi), %r13
movq %r13, 0x8(%rbx)
cmpq 0x10(%rbx), %r13
je 0xb7d1
movl $0x2, -0x18(%rsi)
movl %r14d, -0x14(%rsi)
movl $0x0, -0x10(%rsi)
addq $-0xc, %rsi
movq %rsi, 0x8(%rbx)
jmp 0xb770
leaq 0x404f(%rip), %rdx      # 0xf827
movl $0x1, %esi
movq %rbx, %rdi
callq 0x9432
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 0xb81c
movq %rdi, %r12
movq %rbx, %rdi
movq %rax, %rsi
xorl %edx, %edx
callq 0x8810
movq %r12, %rdi
movq %rax, %r12
jmp 0xb81f
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 0xb861
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 0xb847
addq $0xc, %r14
cmpq %r13, %rbp
je 0xb886
movl 0x8(%r13), %eax
movl %eax, 0x8(%r14)
movq (%r13), %rax
movq %rax, (%r14)
addq $0xc, %r13
addq $0xc, %r14
cmpq %rbp, %r13
jne 0xb86a
testq %rdi, %rdi
je 0xb897
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 0xb770
leaq 0x40d7(%rip), %rsi      # 0xf992
movl $0x46, %edi
movl $0x2, %edx
xorl %eax, %eax
callq 0x2430