// File: /workspace/github_cpp_makefile_star2_O2/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 $0x28, %rsp
movq %rsi, %rbx
movl %edi, 0x4(%rsp)
movq (%rsi), %rsi
movq 0x8(%rbx), %r14
movq %r14, %rcx
subq %rsi, %rcx
pushq $0xc
popq %r13
movq %rcx, %rax
cqto
idivq %r13
cmpq $0x2, %rax
jb 0xa4f6
leaq (%rsi,%rcx), %r8
movl -0x18(%rsi,%rcx), %edx
movl -0xc(%rsi,%rcx), %eax
movl %edx, %r10d
xorl $0x2, %r10d
movl %eax, %r9d
xorl $0x2, %r9d
orl %r9d, %r10d
jne 0xa44a
addl $-0x14, %edi
cmpl $0xf, %edi
ja 0xa708
leaq 0x35c1(%rip), %rax      # 0xd9f0
movslq (%rax,%rdi,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl -0x14(%r8), %edi
movl -0x8(%r8), %esi
callq 0xa36c
jmp 0xa5d8
cmpl $0x2, %edx
jne 0xa49a
cmpl $0x1a, %edi
jne 0xa4f6
cmpl $0x3, %eax
jne 0xa4f6
leaq (%rsi,%rcx), %rax
addq $-0xc, %rax
movl 0x8(%rax), %ecx
leaq 0x18(%rsp), %rsi
movl %ecx, 0x8(%rsi)
movq (%rax), %rax
movq %rax, (%rsi)
movl -0x8(%r8), %eax
addl -0x14(%r8), %eax
movl %eax, 0x4(%rsi)
addq $-0x18, %r14
movq %r14, 0x8(%rbx)
movq %rbx, %rdi
callq 0xa9e2
jmp 0xa5e4
xorl $0x3, %edx
orl %edx, %r9d
jne 0xa4b9
cmpl $0x1b, %edi
je 0xa50a
cmpl $0x1a, %edi
jne 0xa4f6
movl -0x8(%r8), %eax
addl %eax, -0x14(%r8)
jmp 0xa63e
xorl $0x3, %eax
orl %eax, %edx
jne 0xa4f6
movl -0x10(%r8), %eax
cmpl -0x4(%r8), %eax
jne 0xa4f6
addl $-0x1b, %edi
cmpl $0x8, %edi
ja 0xa4f6
leaq 0x34f3(%rip), %rax      # 0xd9cc
movslq (%rax,%rdi,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movl -0x14(%r8), %eax
xorl %r12d, %r12d
cmpl -0x8(%r8), %eax
seta %r12b
jmp 0xa61f
leaq 0x4(%rsp), %rsi
movq %rbx, %rdi
callq 0xa9a8
xorl %eax, %eax
jmp 0xa5e6
movl -0x8(%r8), %eax
subl %eax, -0x14(%r8)
jmp 0xa63e
movl -0x14(%r8), %ecx
xorl %eax, %eax
cmpl -0x8(%r8), %ecx
seta %al
jmp 0xa5d8
movl -0x14(%r8), %ecx
xorl %eax, %eax
cmpl -0x8(%r8), %ecx
sete %al
jmp 0xa5d8
movl -0x14(%r8), %eax
movb -0x8(%r8), %cl
shrl %cl, %eax
jmp 0xa5d8
movl -0x14(%r8), %ecx
xorl %eax, %eax
cmpl -0x8(%r8), %ecx
setg %al
jmp 0xa5d8
movl -0x8(%r8), %eax
orl -0x14(%r8), %eax
jmp 0xa5d8
movl -0x14(%r8), %eax
xorl %edx, %edx
divl -0x8(%r8)
jmp 0xa5d8
movl -0x14(%r8), %ecx
xorl %eax, %eax
cmpl -0x8(%r8), %ecx
setb %al
jmp 0xa5d8
movl -0x14(%r8), %eax
xorl %edx, %edx
divl -0x8(%r8)
movl %edx, %eax
jmp 0xa5d8
movl -0x14(%r8), %eax
subl -0x8(%r8), %eax
jmp 0xa5d8
movl -0x8(%r8), %eax
imull -0x14(%r8), %eax
jmp 0xa5d8
movl -0x14(%r8), %eax
movb -0x8(%r8), %cl
shll %cl, %eax
jmp 0xa5d8
movl -0x14(%r8), %ecx
xorl %eax, %eax
cmpl -0x8(%r8), %ecx
setl %al
jmp 0xa5d8
movl -0x8(%r8), %eax
addl -0x14(%r8), %eax
jmp 0xa5d8
movl -0x8(%r8), %eax
xorl -0x14(%r8), %eax
jmp 0xa5d8
movl -0x8(%r8), %eax
andl -0x14(%r8), %eax
leaq -0xc(%r14), %rcx
movq %rcx, 0x8(%rbx)
movl %eax, -0x14(%r14)
movb $0x1, %al
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl -0x14(%r8), %eax
xorl %r12d, %r12d
cmpl -0x8(%r8), %eax
setb %r12b
jmp 0xa61f
movl -0x14(%r8), %eax
xorl %r12d, %r12d
cmpl -0x8(%r8), %eax
sete %r12b
jmp 0xa61f
movl -0x14(%r8), %r12d
subl -0x8(%r8), %r12d
leaq -0x18(%r14), %rbp
movq %rbp, 0x8(%rbx)
cmpq 0x10(%rbx), %rbp
je 0xa648
movl $0x2, -0x18(%r14)
movl %r12d, -0x14(%r14)
andl $0x0, -0x10(%r14)
addq $-0xc, %r14
movq %r14, 0x8(%rbx)
jmp 0xa5e4
leaq 0x3290(%rip), %rdx      # 0xd8df
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x8474
movq (%rbx), %rcx
movq %rcx, 0x8(%rsp)
movq 0x8(%rbx), %r15
movq %rbp, %r14
subq %rcx, %r14
movq %rbx, %rdi
movq %rax, 0x10(%rsp)
movq %rax, %rsi
callq 0x7974
movq 0x8(%rsp), %rsi
movl $0x2, (%rax,%r14)
movl %r12d, 0x4(%rax,%r14)
movq %rax, %r12
andl $0x0, 0x8(%rax,%r14)
leaq 0xc(%rax), %r14
movq %rsi, %rax
cmpq %rbp, %rax
je 0xa6d3
leaq -0xc(%r14), %rcx
movl 0x8(%rax), %edx
movl %edx, 0x8(%rcx)
movq (%rax), %rdx
movq %rdx, (%rcx)
addq $0xc, %rax
addq $0xc, %r14
jmp 0xa69e
movl 0x8(%rbp), %eax
movl %eax, 0x8(%r14)
movq (%rbp), %rax
movq %rax, (%r14)
addq $0xc, %rbp
addq $0xc, %r14
cmpq %r15, %rbp
jne 0xa6bd
movq 0x10(%rbx), %rax
subq %rsi, %rax
cqto
idivq %r13
movq %rbx, %rdi
movq %rax, %rdx
callq 0x6932
movq %r12, (%rbx)
movq %r14, 0x8(%rbx)
imulq $0xc, 0x10(%rsp), %rax
addq %rax, %r12
movq %r12, 0x10(%rbx)
jmp 0xa5e4
leaq 0x333b(%rip), %rsi      # 0xda4a
pushq $0x46
popq %rdi
pushq $0x2
popq %rdx
xorl %eax, %eax
callq 0x2430