// File: /workspace/github_cpp_makefile_star2_O3/ksherlock[P]wdc-utils/link.cpp
// Function: one_module(std::vector<unsigned char, std::allocator<unsigned char>> const&, std::vector<unsigned char, std::allocator<unsigned char>> const&, std::vector<unsigned char, std::allocator<unsigned char>> const&, std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>>>*)
void one_module(const std::vector<uint8_t> &data, 
	const std::vector<uint8_t> &section_data, 
	const std::vector<uint8_t> &symbol_data,
	std::set<std::string> *local_undefined = nullptr) {

	std::array<int, 256> remap_section;


	std::fill(remap_section.begin(), remap_section.end(), -1);
	remap_section[SECT_PAGE0] = SECT_PAGE0;
	remap_section[SECT_CODE] = SECT_CODE;
	remap_section[SECT_KDATA] = SECT_KDATA;
	remap_section[SECT_DATA] = SECT_DATA;
	remap_section[SECT_UDATA] = SECT_UDATA;

	std::vector<section> local_sections = read_sections(section_data);
	std::vector<symbol> local_symbols = read_symbols(symbol_data);



	// convert local sections to global 
	for (auto &s : local_sections) {
		//printf("section %20s %d\n", s.name.c_str(), s.number);

		if (s.number <= SECT_UDATA) {
			sections[s.number].size += s.size; // for page0 / udata sections.
			continue;
		}


		// todo -- should install section name as global symbol?

		auto iter = section_map.find(s.name);
		if (iter == section_map.end()) {

			int virtual_section = sections.size();
			remap_section[s.number] = virtual_section;
			s.number = virtual_section;

			if (!(s.flags & SEC_NONAME)) {
				/* generate an _BEG_name_ and _END_name */

				symbol sym;

				sym.name = "_BEG_" + s.name;
				upper_case(sym.name);
				sym.section = virtual_section;
				sym.type = S_REL; // check if section has offset?
				sym.flags = SF_DEF | SF_GBL;


				auto iter = symbol_map.find(sym.name);
				if (iter == symbol_map.end()) {
					symbol_map.emplace(sym.name, symbols.size());
					symbols.emplace_back(std::move(sym));
				} else {
					// duplicate label error...
				}


/*
				// add entry for name? or handle via undefined symbol lookup below?
				handled at end if symbol undeinfed.

				sym.name = s.name;
				sym.section = virtual_section;
				sym.type = S_REL;
				sym.flags = SF_DEF | SF_GBL;

				iter = symbol_map.find(sym.name);
				if (iter == symbol_map.end()) {
					symbol_map.emplace(sym.name, symbols.size());
					symbols.emplace_back(std::move(sym));
				} else {
					// duplicate label error...
				}
*/

				sym.name = "_END_" + s.name;
				upper_case(sym.name);

				sym.section = symbols.size();
				sym.type = S_UND;
				sym.flags = 0;

				iter = symbol_map.find(sym.name);
				if (iter == symbol_map.end()) {
					s.end_symbol = sym.section;
					symbol_map.emplace(sym.name, sym.section);
					symbols.emplace_back(std::move(sym));	
				} else {
					// duplicate label...
				}



			}

			sections.emplace_back(s);
			section_map.emplace(s.name, virtual_section);

		} else {
			auto &ss = sections[iter->second];
			assert(ss.flags == s.flags); // check org????
			remap_section[s.number] = iter->second;
			s.number = iter->second;

			// update size (for ref-only sections)
			ss.size += s.size;
		}
	}



	// convert local symbols to global.
	for (auto &s : local_symbols) {

		if (flags.v) {
			const char *status = "";
			if (s.type == S_UND) status = "extern";
			else if (s.flags & SF_GBL) status = "public";
			else status = "private";
			fprintf(stderr, "  %-20s [%s]\n", s.name.c_str(), status);
		}

		if (s.type == S_UND) {


			auto iter = symbol_map.find(s.name);
			if (iter == symbol_map.end()) {
				s.section = symbols.size();
				symbol_map.emplace(s.name, s.section);
				symbols.emplace_back(s);
				undefined_symbols.emplace(s.name);

				fprintf(stderr, "Adding %s to undefined symbols\n", s.name.c_str());
			}
			else {
				// already exists... 
				const auto &ss = symbols[iter->second];
				/* if (ss.type != S_UND) */
				// always copy over since s.section is a big deal.
				s = ss;
			}

			if (local_undefined) {
				if (s.type == S_UND) local_undefined->emplace(s.name);
			}
			continue;
		}

		// remap and fudge the offset.
		if ((s.type & 0x0f) == S_REL) {
			int virtual_section = remap_section[s.section];
			assert(virtual_section != -1);
			s.section = virtual_section;
			s.offset += sections[virtual_section].data.size();
		} else {
			s.section = -1;
		}



		constexpr const unsigned mask = SF_GBL | SF_DEF;
		if ((s.flags & mask) == mask) {

			auto iter = symbol_map.find(s.name);

			if (iter == symbol_map.end()) {
				unsigned tmp = symbols.size();
				symbol_map.emplace(s.name, tmp);
				symbols.emplace_back(s);
			} else {
				auto &ss = symbols[iter->second];

				// if it was undefined, define it!
				if (ss.type == S_UND) {
					ss = s;
					undefined_symbols.erase(s.name);
				}
				else {
					// ok if symbols are identical..
					if (ss.type != s.type || ss.flags != s.flags || ss.section != s.section || ss.offset != s.offset) {
						warnx("Duplicate label %s", s.name.c_str());
						flags.errors++;
					} 
				}
			}

		}

	}

	// set it here. sections may be resized above.
	int current_section = SECT_CODE;
	std::vector<uint8_t> *data_ptr = &sections[current_section].data;


	auto iter = data.begin();
	for(;;) {
		uint8_t op = read_8(iter);
		if (op == REC_END) return;

		if (op < 0xf0) {
			data_ptr->insert(data_ptr->end(), iter, iter + op);
			iter += op;
			continue;
		}

		switch(op) {
			case REC_SPACE: {
				uint16_t count = read_16(iter);
				data_ptr->insert(data_ptr->end(), count, 0);
				break;
			}

			case REC_SECT: {
				/* switch sections */
				uint8_t s = read_8(iter);
				current_section = remap_section[s];
				assert(current_section > 0 && current_section < sections.size());

				data_ptr = &sections[current_section].data;
				break;
			}

			case REC_ORG: {
				assert(!"ORG not supported.");
				break;
			}

			case REC_RELEXP:
			case REC_EXPR: {

				expression e;
				e.relative = op == REC_RELEXP;
				e.section = current_section;

				e.offset =  data_ptr->size();
				e.size = read_8(iter);


				data_ptr->insert(data_ptr->end(), e.size, 0);

				int reduced_size = 0;
				/**/
				for(;;) {
					op = read_8(iter);
					if (op == OP_END) break;

					switch(op) {
						case OP_VAL: {
							reduced_size++;
							uint32_t offset = read_32(iter);
							e.stack.emplace_back(op, offset);
							break;
						}
						case OP_SYM: {
							reduced_size++;
							uint16_t symbol = read_16(iter);
							assert(symbol < local_symbols.size());
							auto &s = local_symbols[symbol];
							switch (s.type & 0x0f) {
								case S_UND:
									// S_UND indicates it's still undefined globally.
									e.stack.emplace_back(OP_SYM, 0, s.section); /* section is actually a symbol number */
									e.undefined = true;
									break;

								case S_REL:
									e.stack.emplace_back(OP_LOC, s.offset, s.section);
									break;

								case S_ABS:
									e.stack.emplace_back(OP_VAL, s.offset);
									break;

								default:
									assert(!"unsupported symbol flags.");
							}
							break;
						}
						case OP_LOC: {
							reduced_size++;
							uint8_t section = read_8(iter);
							uint32_t offset = read_32(iter);
							int real_section = remap_section[section];
							assert(real_section >= 0);
							e.stack.emplace_back(op, offset, real_section);
							break;
						}
						// operations..
						//unary
						case OP_NOT:
						case OP_NEG:
						case OP_FLP:
							e.stack.emplace_back(op);
							break;
						// binary
						case OP_EXP:
						case OP_MUL:
						case OP_DIV:
						case OP_MOD:
						case OP_SHR:
						case OP_SHL:
						case OP_ADD:
						case OP_SUB:
						case OP_AND:
						case OP_OR:
						case OP_XOR:
						case OP_EQ:
						case OP_GT:
						case OP_LT:
						case OP_UGT:
						case OP_ULT:
							reduced_size--;
							e.stack.emplace_back(op);
							break;
						default:
							assert(!"unsupported expression opcode.");
					}
				}

				if (reduced_size != 1) {
					expr_error(true, e, "Malformed expression");
				}
				sections[current_section].expressions.emplace_back(std::move(e));
				break;
			}


			case REC_LINE: break;
			case REC_DEBUG: {
				uint16_t size = read_16(iter);
				iter += size;
				break;		
			}

		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4b8, %rsp            # imm = 0x4B8
movq %rcx, 0x8(%rsp)
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
leaq 0xc4(%rsp), %r12
movl $0x3ec, %edx            # imm = 0x3EC
movq %r12, %rdi
movl $0xff, %esi
callq 0x2170
movaps 0xc06d(%rip), %xmm0     # 0xf010
movaps %xmm0, -0x14(%r12)
movl $0x4, -0x4(%r12)
leaq 0x98(%rsp), %rdi
movq %r15, %rsi
callq 0x2ab4
leaq 0x80(%rsp), %rdi
movq %r14, %rsi
callq 0x2c99
movq %rbx, 0x48(%rsp)
movq 0x98(%rsp), %r15
movq 0xa0(%rsp), %rbp
cmpq %rbp, %r15
je 0x32c2
leaq 0x122d1(%rip), %r14     # 0x152c8
leaq 0x58(%rsp), %rbx
leaq 0x10(%rsp), %r12
movl 0x2c(%r15), %eax
cmpq $0x4, %rax
ja 0x3023
movl 0x28(%r15), %ecx
movq 0x122ea(%rip), %rdx     # 0x15300
imulq $0x68, %rax, %rax
addl %ecx, 0x28(%rdx,%rax)
jmp 0x32b5
movq %r14, %rdi
movq %r15, %rsi
callq 0x7e6c
testq %rax, %rax
je 0x306f
movslq 0x28(%rax), %rcx
movq 0x122c2(%rip), %rax     # 0x15300
imulq $0x68, %rcx, %rdx
movb 0x20(%rax,%rdx), %sil
cmpb 0x20(%r15), %sil
jne 0x3c8f
addq %rdx, %rax
movl 0x2c(%r15), %edx
movl %ecx, 0xb0(%rsp,%rdx,4)
movl %ecx, 0x2c(%r15)
movl 0x28(%r15), %ecx
addl %ecx, 0x28(%rax)
jmp 0x32b5
movq 0x12292(%rip), %rax     # 0x15308
subq 0x12283(%rip), %rax     # 0x15300
shrq $0x3, %rax
imull $0xc4ec4ec5, %eax, %eax # imm = 0xC4EC4EC5
movl %eax, 0x44(%rsp)
movl 0x2c(%r15), %ecx
movl %eax, 0xb0(%rsp,%rcx,4)
movl %eax, 0x2c(%r15)
testb $0x40, 0x20(%r15)
jne 0x3296
leaq 0x20(%rsp), %rax
movq %rax, 0x10(%rsp)
movq $0x0, 0x18(%rsp)
movb $0x0, 0x20(%rsp)
movw $0x0, 0x30(%rsp)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0x34(%rsp)
movq %rbx, %rdi
leaq 0xbfcf(%rip), %rsi      # 0xf0ac
movq %r15, %rdx
callq 0x5ea7
movq %r12, %r13
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22e0
movq 0x58(%rsp), %rdi
leaq 0x68(%rsp), %rax
cmpq %rax, %rdi
je 0x310f
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x2260
movq 0x18(%rsp), %rbx
testq %rbx, %rbx
je 0x3137
movq 0x10(%rsp), %r12
xorl %r14d, %r14d
movsbl (%r12,%r14), %edi
callq 0x2410
movb %al, (%r12,%r14)
incq %r14
cmpq %r14, %rbx
jne 0x3121
movl 0x44(%rsp), %eax
movl %eax, 0x38(%rsp)
movw $0x302, 0x30(%rsp)      # imm = 0x302
leaq 0x121cb(%rip), %rdi     # 0x15318
movq %r13, %r14
movq %r13, %rsi
callq 0x7e6c
leaq 0x58(%rsp), %rbx
testq %rax, %rax
jne 0x31a8
movq 0x121ef(%rip), %rax     # 0x15358
subq 0x121e0(%rip), %rax     # 0x15350
sarq $0x4, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rax
movq %rax, 0x58(%rsp)
leaq 0x1218a(%rip), %rdi     # 0x15318
movq %r14, %rsi
movq %rbx, %rdx
callq 0x7f84
leaq 0x121b0(%rip), %rdi     # 0x15350
movq %r14, %rsi
callq 0x5dc2
movq %rbx, %rdi
leaq 0xbf00(%rip), %rsi      # 0xf0b2
movq %r15, %rdx
callq 0x5ea7
movq %r14, %rdi
movq %rbx, %rsi
callq 0x22e0
movq 0x58(%rsp), %rdi
leaq 0x68(%rsp), %rax
cmpq %rax, %rdi
je 0x31e1
movq 0x68(%rsp), %rsi
incq %rsi
callq 0x2260
movq 0x18(%rsp), %rbx
testq %rbx, %rbx
je 0x3209
movq 0x10(%rsp), %r12
xorl %r14d, %r14d
movsbl (%r12,%r14), %edi
callq 0x2410
movb %al, (%r12,%r14)
incq %r14
cmpq %r14, %rbx
jne 0x31f3
movq 0x12148(%rip), %rax     # 0x15358
subq 0x12139(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, 0x38(%rsp)
movw $0x0, 0x30(%rsp)
leaq 0x120e5(%rip), %rdi     # 0x15318
movq %r13, %r12
movq %r13, %rsi
callq 0x7e6c
testq %rax, %rax
leaq 0x58(%rsp), %rbx
leaq 0x1207b(%rip), %r14     # 0x152c8
jne 0x327a
movl 0x38(%rsp), %eax
movl %eax, 0x60(%r15)
leaq 0x120ba(%rip), %rdi     # 0x15318
movq %r12, %rsi
leaq 0x38(%rsp), %rdx
callq 0x82ca
leaq 0x120de(%rip), %rdi     # 0x15350
movq %r12, %rsi
callq 0x5dc2
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3296
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x12063(%rip), %rdi     # 0x15300
movq %r15, %rsi
callq 0x5f30
movq %r14, %rdi
movq %r15, %rsi
leaq 0x44(%rsp), %rdx
callq 0x82ca
addq $0x68, %r15
cmpq %rbp, %r15
jne 0x3001
movq 0x80(%rsp), %r14
movq 0x88(%rsp), %r13
cmpq %r13, %r14
je 0x351f
addq $0x28, %r14
leaq -0x28(%r14), %rbp
cmpb $0x1, 0x11f76(%rip)     # 0x15260
je 0x34ba
leaq -0x8(%r14), %rbx
movb -0x8(%r14), %al
testb %al, %al
je 0x3337
andb $0xf, %al
cmpb $0x2, %al
jne 0x33a4
movslq (%r14), %rax
movslq 0xb0(%rsp,%rax,4), %rax
cmpq $-0x1, %rax
je 0x3cae
movl %eax, (%r14)
movq 0x11fdb(%rip), %rcx     # 0x15300
imulq $0x68, %rax, %rax
movl 0x38(%rcx,%rax), %edx
subl 0x30(%rcx,%rax), %edx
addl %edx, -0x4(%r14)
jmp 0x33ab
leaq 0x11fda(%rip), %rdi     # 0x15318
movq %rbp, %rsi
callq 0x7e6c
testq %rax, %rax
je 0x34c7
movslq 0x28(%rax), %rax
leaq (%rax,%rax,2), %r12
shlq $0x4, %r12
addq 0x11fee(%rip), %r12     # 0x15350
movq %rbp, %rdi
movq %r12, %rsi
callq 0x2160
movl 0x28(%r12), %eax
movl %eax, 0x8(%rbx)
movq 0x20(%r12), %rax
movq %rax, (%rbx)
cmpq $0x0, 0x8(%rsp)
je 0x34a4
cmpb $0x0, (%rbx)
jne 0x34a4
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
callq 0x8a46
jmp 0x34a4
movl $0xffffffff, (%r14)     # imm = 0xFFFFFFFF
movb -0x7(%r14), %al
notb %al
testb $0x3, %al
jne 0x34a4
leaq 0x11f58(%rip), %rdi     # 0x15318
movq %rbp, %rsi
callq 0x7e6c
testq %rax, %rax
je 0x3429
movslq 0x28(%rax), %rax
movq 0x11f78(%rip), %r12     # 0x15350
leaq (%rax,%rax,2), %r15
shlq $0x4, %r15
leaq (%r12,%r15), %rdi
movb 0x20(%r12,%r15), %al
testb %al, %al
je 0x346a
cmpb (%rbx), %al
jne 0x340f
movb 0x21(%rdi), %al
cmpb -0x7(%r14), %al
jne 0x340f
movl 0x28(%rdi), %eax
cmpl (%r14), %eax
jne 0x340f
movl 0x24(%rdi), %eax
cmpl -0x4(%r14), %eax
je 0x34a4
movq (%rbp), %rsi
leaq 0xbd98(%rip), %rdi      # 0xf1b2
xorl %eax, %eax
callq 0x2290
incl 0x11e91(%rip)           # 0x152b8
jmp 0x34a4
movq 0x11f28(%rip), %rax     # 0x15358
subq 0x11f19(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, 0x10(%rsp)
leaq 0x11ecc(%rip), %rdi     # 0x15318
movq %rbp, %rsi
leaq 0x10(%rsp), %rdx
callq 0x8c28
leaq 0x11ef0(%rip), %rdi     # 0x15350
movq %rbp, %rsi
callq 0x5f6a
jmp 0x34a4
movq %rbp, %rsi
callq 0x2160
leaq (%r12,%r15), %rax
addq $0x20, %rax
movl 0x8(%rbx), %ecx
movl %ecx, 0x8(%rax)
movq (%rbx), %rcx
movq %rcx, (%rax)
leaq 0x11edb(%rip), %rdi     # 0x15368
movq %rbp, %rsi
callq 0x8d58
leaq 0x11ecc(%rip), %rdi     # 0x15368
movq %rax, %rsi
callq 0x8e0c
leaq 0x30(%r14), %rax
addq $0x8, %r14
cmpq %r13, %r14
movq %rax, %r14
jne 0x32df
jmp 0x351f
movq %rbp, %rdi
callq 0x2480
jmp 0x32f0
movq 0x11e8a(%rip), %rax     # 0x15358
subq 0x11e7b(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, (%r14)
leaq 0x11e2f(%rip), %rdi     # 0x15318
movq %rbp, %rsi
movq %r14, %rdx
callq 0x82ca
leaq 0x11e55(%rip), %rdi     # 0x15350
movq %rbp, %rsi
callq 0x5f6a
leaq 0x11e5e(%rip), %rdi     # 0x15368
movq %rbp, %rsi
callq 0x8a46
movq %rbp, %rdi
callq 0x24c9
jmp 0x337d
movq 0x11dda(%rip), %rax     # 0x15300
movq %rax, 0x50(%rsp)
movq 0x48(%rsp), %rax
movq (%rax), %r14
movb (%r14), %al
movb %al, 0x7(%rsp)
testb %al, %al
je 0x3bc3
addq $0x98, 0x50(%rsp)
movl $0x1, %ecx
movq %rcx, 0x78(%rsp)
leaq 0x20(%rsp), %rbx
leaq 0xbacf(%rip), %r13      # 0xf030
leaq 0x58(%rsp), %rbp
leaq 0x7(%rsp), %r15
leaq 0x1(%r14), %r12
cmpb $-0x11, %al
ja 0x3597
movq 0x50(%rsp), %rdi
movq 0x8(%rdi), %rsi
movzbl %al, %ecx
addq %r12, %rcx
movq %r12, %rdx
callq 0x8f3a
movzbl 0x7(%rsp), %eax
addq %rax, %r12
jmp 0x3bb0
movzbl %al, %ecx
addl $0xffffff10, %ecx       # imm = 0xFFFFFF10
cmpl $0x5, %ecx
ja 0x3bb0
movslq (%r13,%rcx,4), %rcx
addq %r13, %rcx
jmpq *%rcx
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
xorl %ecx, %ecx
movq %rcx, 0x10(%rbx)
movq %rcx, 0x10(%rsp)
movl $0x0, 0x17(%rsp)
cmpb $-0xc, %al
sete 0x19(%rsp)
movq 0x78(%rsp), %rax
movl %eax, 0x10(%rsp)
movq 0x50(%rsp), %rdi
movq 0x8(%rdi), %rsi
movl (%rdi), %eax
movl %esi, %ecx
subl %eax, %ecx
movl %ecx, 0x14(%rsp)
movzbl (%r12), %edx
movb %dl, 0x18(%rsp)
movb $0x0, 0x58(%rsp)
movq %rbp, %rcx
callq 0x9122
addq $0x2, %r14
xorl %r13d, %r13d
movzbl (%r14), %eax
leaq 0x1(%r14), %r12
movb %al, 0x7(%rsp)
leal -0x14(%rax), %ecx
cmpl $0x10, %ecx
jae 0x3633
decl %r13d
movq %rbx, %rdi
movq %r15, %rsi
callq 0x605c
movq %r12, %r14
jmp 0x360c
cmpl $0xc, %eax
ja 0x3bef
movl %eax, %eax
leaq 0xba03(%rip), %rcx      # 0xf048
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
movq %r15, %rsi
callq 0x605c
movq %r12, %r14
jmp 0x360c
movl (%r12), %eax
movl %eax, 0x58(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
movq %rbp, %rdx
callq 0x5fd2
addq $0x5, %r14
incl %r13d
jmp 0x360c
movzwl 0x1(%r14), %ecx
movq 0x80(%rsp), %rax
movq 0x88(%rsp), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
movabsq $-0x5555555555555555, %rsi # imm = 0xAAAAAAAAAAAAAAAB
imulq %rsi, %rdx
cmpq %rcx, %rdx
jbe 0x3c2d
incl %r13d
addq $0x3, %r14
leaq (%rcx,%rcx,2), %rcx
shll $0x4, %ecx
leaq (%rax,%rcx), %r15
movzbl 0x20(%rax,%rcx), %eax
andl $0xf, %eax
cmpl $0x2, %eax
je 0x3784
cmpl $0x1, %eax
je 0x3753
testl %eax, %eax
jne 0x3c4c
movq 0x28(%rsp), %r12
cmpq 0x30(%rsp), %r12
je 0x38b6
movl 0x28(%r15), %eax
movq $0x1, (%r12)
movl %eax, 0x8(%r12)
addq $0xc, %r12
movq %r12, 0x28(%rsp)
leaq 0x7(%rsp), %r15
jmp 0x3ab2
movzbl 0x1(%r14), %eax
movl 0x2(%r14), %ecx
movl %ecx, 0x58(%rsp)
movl 0xb0(%rsp,%rax,4), %eax
movl %eax, 0x44(%rsp)
testl %eax, %eax
js 0x3c0e
movq %rbx, %rdi
movq %r15, %rsi
movq %rbp, %rdx
leaq 0x44(%rsp), %rcx
callq 0x6016
incl %r13d
addq $0x6, %r14
jmp 0x360c
movq %r15, 0x8(%rsp)
movq 0x28(%rsp), %r12
cmpq 0x30(%rsp), %r12
je 0x37c2
movq 0x8(%rsp), %rax
movl 0x24(%rax), %eax
movl $0x2, (%r12)
movl %eax, 0x4(%r12)
movl $0x0, 0x8(%r12)
jmp 0x37af
movq %r15, 0x8(%rsp)
movq 0x28(%rsp), %r12
cmpq 0x30(%rsp), %r12
je 0x383c
movq 0x8(%rsp), %rax
movq 0x24(%rax), %rax
movl $0x3, (%r12)
movq %rax, 0x4(%r12)
addq $0xc, %r12
movq %r12, 0x28(%rsp)
leaq 0x7(%rsp), %r15
jmp 0x360c
movq 0x20(%rsp), %rax
movq %r12, %rbp
movq %rax, 0x48(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c77
sarq $0x2, %rbp
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rbp
cmpq $0x1, %rbp
movq %rbp, %rax
adcq $0x0, %rax
leaq (%rax,%rbp), %rsi
movabsq $0xaaaaaaaaaaaaaaa, %rcx # imm = 0xAAAAAAAAAAAAAAA
cmpq %rcx, %rsi
cmovaeq %rcx, %rsi
addq %rbp, %rax
cmovbq %rcx, %rsi
testq %rsi, %rsi
je 0x3934
movq %rbx, %rdi
movq %rsi, %r15
xorl %edx, %edx
callq 0x8810
movq %r15, %rsi
jmp 0x3936
movq 0x20(%rsp), %rax
movq %r12, %rbp
movq %rax, 0x48(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c83
sarq $0x2, %rbp
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rbp
cmpq $0x1, %rbp
movq %rbp, %rax
adcq $0x0, %rax
leaq (%rax,%rbp), %rsi
movabsq $0xaaaaaaaaaaaaaaa, %rcx # imm = 0xAAAAAAAAAAAAAAA
cmpq %rcx, %rsi
cmovaeq %rcx, %rsi
addq %rbp, %rax
cmovbq %rcx, %rsi
testq %rsi, %rsi
je 0x398b
movq %rbx, %rdi
movq %rsi, %r15
xorl %edx, %edx
callq 0x8810
movq %r15, %rsi
jmp 0x398d
movq 0x20(%rsp), %rax
movq %r12, %rbp
movq %rax, 0x48(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c6b
sarq $0x2, %rbp
movabsq $-0x5555555555555555, %rax # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rbp
cmpq $0x1, %rbp
movq %rbp, %rax
adcq $0x0, %rax
leaq (%rax,%rbp), %rsi
movabsq $0xaaaaaaaaaaaaaaa, %rcx # imm = 0xAAAAAAAAAAAAAAA
cmpq %rcx, %rsi
cmovaeq %rcx, %rsi
addq %rbp, %rax
cmovbq %rcx, %rsi
testq %rsi, %rsi
movq %rsi, 0x8(%rsp)
je 0x3a26
movq %rbx, %rdi
xorl %edx, %edx
callq 0x8810
movq 0x8(%rsp), %rsi
jmp 0x3a28
xorl %eax, %eax
leaq (,%rbp,2), %rdx
addq %rbp, %rdx
movq 0x8(%rsp), %rcx
movl 0x24(%rcx), %ecx
movl $0x2, (%rax,%rdx,4)
movl %ecx, 0x4(%rax,%rdx,4)
movl $0x0, 0x8(%rax,%rdx,4)
movq %rax, %rbp
movq 0x48(%rsp), %rdi
cmpq %r12, %rdi
je 0x39da
movq %rax, %rbp
movq %rdi, %rdx
movl 0x8(%rdx), %ecx
movl %ecx, 0x8(%rbp)
movq (%rdx), %rcx
movq %rcx, (%rbp)
addq $0xc, %rdx
addq $0xc, %rbp
cmpq %r12, %rdx
jne 0x396f
jmp 0x39da
xorl %eax, %eax
leaq (,%rbp,2), %rdx
addq %rbp, %rdx
movq 0x8(%rsp), %rcx
movq 0x24(%rcx), %rcx
movl $0x3, (%rax,%rdx,4)
movq %rcx, 0x4(%rax,%rdx,4)
movq %rax, %rbp
movq 0x48(%rsp), %rdi
cmpq %r12, %rdi
je 0x39da
movq %rax, %rbp
movq %rdi, %rdx
movl 0x8(%rdx), %ecx
movl %ecx, 0x8(%rbp)
movq (%rdx), %rcx
movq %rcx, (%rbp)
addq $0xc, %rdx
addq $0xc, %rbp
cmpq %r12, %rdx
jne 0x39c0
testq %rdi, %rdi
leaq 0x7(%rsp), %r15
je 0x3a01
movq %rsi, 0x8(%rsp)
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
movq %rax, %r12
callq 0x2260
movq %r12, %rax
movq 0x8(%rsp), %rsi
addq $0xc, %rbp
movq %rax, 0x20(%rsp)
movq %rbp, 0x28(%rsp)
leaq (%rsi,%rsi,2), %rcx
leaq (%rax,%rcx,4), %rax
movq %rax, 0x30(%rsp)
leaq 0x58(%rsp), %rbp
jmp 0x360c
xorl %eax, %eax
leaq (,%rbp,2), %rdx
addq %rbp, %rdx
movl 0x28(%r15), %ecx
movq $0x1, (%rax,%rdx,4)
movl %ecx, 0x8(%rax,%rdx,4)
movq %rax, %rbp
movq 0x48(%rsp), %rdi
cmpq %r12, %rdi
je 0x3a70
movq %rax, %rbp
movq %rdi, %rdx
movl 0x8(%rdx), %ecx
movl %ecx, 0x8(%rbp)
movq (%rdx), %rcx
movq %rcx, (%rbp)
addq $0xc, %rdx
addq $0xc, %rbp
cmpq %r12, %rdx
jne 0x3a56
testq %rdi, %rdi
leaq 0x7(%rsp), %r15
je 0x3a92
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
movq %rax, %r12
callq 0x2260
movq %r12, %rax
movq 0x8(%rsp), %rsi
addq $0xc, %rbp
movq %rax, 0x20(%rsp)
movq %rbp, 0x28(%rsp)
leaq (%rsi,%rsi,2), %rcx
leaq (%rax,%rcx,4), %rax
movq %rax, 0x30(%rsp)
leaq 0x58(%rsp), %rbp
movb $0x1, 0x1a(%rsp)
jmp 0x360c
cmpl $0x1, %r13d
je 0x3ad8
movl $0x1, %edi
leaq 0x10(%rsp), %rsi
leaq 0xb7b0(%rip), %rdx      # 0xf283
callq 0x6099
movl 0x78(%rsp), %eax
movq 0x1181d(%rip), %rcx     # 0x15300
imulq $0x68, %rax, %rax
leaq (%rcx,%rax), %rdi
addq $0x48, %rdi
leaq 0x10(%rsp), %rsi
callq 0x6d2e
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
leaq 0xb528(%rip), %r13      # 0xf030
je 0x3bb0
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
jmp 0x3bb0
movzbl 0x1(%r14), %eax
movslq 0xb0(%rsp,%rax,4), %rsi
testq %rsi, %rsi
jle 0x3ccd
movq 0x117cb(%rip), %rcx     # 0x15308
movq 0x117bc(%rip), %rax     # 0x15300
subq %rax, %rcx
sarq $0x3, %rcx
movabsq $0x4ec4ec4ec4ec4ec5, %rdx # imm = 0x4EC4EC4EC4EC4EC5
imulq %rdx, %rcx
cmpq %rsi, %rcx
jbe 0x3ccd
addq $0x2, %r14
movq %rsi, 0x78(%rsp)
imulq $0x68, %rsi, %rcx
addq %rcx, %rax
addq $0x30, %rax
movq %rax, 0x50(%rsp)
jmp 0x3bad
movzwl 0x1(%r14), %eax
leaq (%r14,%rax), %r12
addq $0x3, %r12
jmp 0x3bb0
movzwl (%r12), %edx
movq 0x50(%rsp), %rdi
movq 0x8(%rdi), %rsi
movb $0x0, 0x10(%rsp)
leaq 0x10(%rsp), %rcx
callq 0x9122
addq $0x3, %r14
movq %r14, %r12
movb (%r12), %al
movb %al, 0x7(%rsp)
movq %r12, %r14
testb %al, %al
jne 0x356b
leaq 0x80(%rsp), %rdi
callq 0x5e3e
leaq 0x98(%rsp), %rdi
callq 0x5d92
addq $0x4b8, %rsp            # imm = 0x4B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb66b(%rip), %rdi      # 0xf261
leaq 0xb4cf(%rip), %rsi      # 0xf0cc
leaq 0xb4d1(%rip), %rcx      # 0xf0d5
movl $0x2e1, %edx            # imm = 0x2E1
callq 0x21c0
leaq 0xb63a(%rip), %rdi      # 0xf24f
leaq 0xb4b0(%rip), %rsi      # 0xf0cc
leaq 0xb4b2(%rip), %rcx      # 0xf0d5
movl $0x2c1, %edx            # imm = 0x2C1
callq 0x21c0
leaq 0xb5e0(%rip), %rdi      # 0xf214
leaq 0xb491(%rip), %rsi      # 0xf0cc
leaq 0xb493(%rip), %rcx      # 0xf0d5
movl $0x2a6, %edx            # imm = 0x2A6
callq 0x21c0
leaq 0xb5df(%rip), %rdi      # 0xf232
leaq 0xb472(%rip), %rsi      # 0xf0cc
leaq 0xb474(%rip), %rcx      # 0xf0d5
movl $0x2b8, %edx            # imm = 0x2B8
callq 0x21c0
leaq 0xbbb5(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xbba9(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xbb9d(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xb422(%rip), %rdi      # 0xf0b8
leaq 0xb42f(%rip), %rsi      # 0xf0cc
leaq 0xb431(%rip), %rcx      # 0xf0d5
movl $0x209, %edx            # imm = 0x209
callq 0x21c0
leaq 0xb4e7(%rip), %rdi      # 0xf19c
leaq 0xb410(%rip), %rsi      # 0xf0cc
leaq 0xb412(%rip), %rcx      # 0xf0d5
movl $0x23c, %edx            # imm = 0x23C
callq 0x21c0
leaq 0xb4f1(%rip), %rdi      # 0xf1c5
leaq 0xb3f1(%rip), %rsi      # 0xf0cc
leaq 0xb3f3(%rip), %rcx      # 0xf0d5
movl $0x27e, %edx            # imm = 0x27E
callq 0x21c0
leaq 0xb50b(%rip), %rdi      # 0xf1fe
leaq 0xb3d2(%rip), %rsi      # 0xf0cc
leaq 0xb3d4(%rip), %rcx      # 0xf0d5
movl $0x285, %edx            # imm = 0x285
callq 0x21c0
jmp 0x3d1c
movq %rax, %rbx
jmp 0x3d84
jmp 0x3d54
jmp 0x3d1c
jmp 0x3d1c
jmp 0x3d1c
jmp 0x3d5d
movq %rax, %rbx
movq 0x10(%rsp), %rdi
leaq 0x20(%rsp), %rax
cmpq %rax, %rdi
je 0x3d77
movq 0x20(%rsp), %rsi
incq %rsi
jmp 0x3d72
jmp 0x3d54
jmp 0x3d5d
jmp 0x3d54
jmp 0x3d54
jmp 0x3d54
jmp 0x3d54
jmp 0x3d5d
jmp 0x3d5d
jmp 0x3d5d
jmp 0x3d54
jmp 0x3d54
jmp 0x3d5d
jmp 0x3d5d
jmp 0x3d5d
movq %rax, %rbx
jmp 0x3d77
jmp 0x3d5d
jmp 0x3d5d
movq %rax, %rbx
movq 0x20(%rsp), %rdi
testq %rdi, %rdi
je 0x3d77
movq 0x30(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
leaq 0x80(%rsp), %rdi
callq 0x5e3e
leaq 0x98(%rsp), %rdi
callq 0x5d92
movq %rbx, %rdi
callq 0x23c0