// File: /workspace/github_cpp_makefile_star2_O1/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, 0x10(%rsp)
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r14
leaq 0xb8(%rsp), %r12
movl $0x400, %edx            # imm = 0x400
movq %r12, %rdi
movl $0xff, %esi
callq 0x2170
movaps 0xc08d(%rip), %xmm0     # 0xf010
movups %xmm0, (%r12)
movl $0x4, 0x10(%r12)
leaq 0xa0(%rsp), %rdi
movq %r15, %rsi
callq 0x2a94
leaq 0x88(%rsp), %rdi
movq %rbx, %rsi
callq 0x2c8b
movq %r14, 0x50(%rsp)
movq 0xa0(%rsp), %r15
movq 0xa8(%rsp), %rbp
cmpq %rbp, %r15
je 0x32a2
leaq 0x122f2(%rip), %r14     # 0x152c8
leaq 0x60(%rsp), %rbx
leaq 0x18(%rsp), %r12
movl 0x2c(%r15), %eax
cmpq $0x4, %rax
ja 0x3002
movl 0x28(%r15), %ecx
movq 0x1230b(%rip), %rdx     # 0x15300
imulq $0x68, %rax, %rax
addl %ecx, 0x28(%rdx,%rax)
jmp 0x3295
movq %r14, %rdi
movq %r15, %rsi
callq 0x7f18
testq %rax, %rax
je 0x3051
movslq 0x28(%rax), %rdx
movq 0x122e3(%rip), %rcx     # 0x15300
imulq $0x68, %rdx, %rsi
movb 0x20(%rcx,%rsi), %dil
cmpb 0x20(%r15), %dil
jne 0x3c91
addq %rsi, %rcx
movl 0x2c(%r15), %esi
movl %edx, 0xb8(%rsp,%rsi,4)
movl 0x28(%rax), %eax
movl %eax, 0x2c(%r15)
movl 0x28(%r15), %eax
addl %eax, 0x28(%rcx)
jmp 0x3295
movq 0x122b0(%rip), %rax     # 0x15308
subq 0x122a1(%rip), %rax     # 0x15300
shrq $0x3, %rax
imull $0xc4ec4ec5, %eax, %eax # imm = 0xC4EC4EC5
movl %eax, 0x4c(%rsp)
movl 0x2c(%r15), %ecx
movl %eax, 0xb8(%rsp,%rcx,4)
movl %eax, 0x2c(%r15)
testb $0x40, 0x20(%r15)
jne 0x3276
leaq 0x28(%rsp), %rax
movq %rax, 0x18(%rsp)
movq $0x0, 0x20(%rsp)
movb $0x0, 0x28(%rsp)
movw $0x0, 0x38(%rsp)
movabsq $-0x100000000, %rax     # imm = 0xFFFFFFFF00000000
movq %rax, 0x3c(%rsp)
movq %rbx, %rdi
leaq 0xbfed(%rip), %rsi      # 0xf0ac
movq %r15, %rdx
callq 0x5f2b
movq %r12, %r13
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22e0
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x30f1
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x2260
movq 0x20(%rsp), %r14
testq %r14, %r14
je 0x3118
movq 0x18(%rsp), %r12
xorl %ebx, %ebx
movsbl (%r12,%rbx), %edi
callq 0x2410
movb %al, (%r12,%rbx)
incq %rbx
cmpq %rbx, %r14
jne 0x3102
movl 0x4c(%rsp), %eax
movl %eax, 0x40(%rsp)
movw $0x302, 0x38(%rsp)      # imm = 0x302
leaq 0x121ea(%rip), %rdi     # 0x15318
movq %r13, %r14
movq %r13, %rsi
callq 0x7f18
leaq 0x60(%rsp), %rbx
testq %rax, %rax
jne 0x3189
movq 0x1220e(%rip), %rax     # 0x15358
subq 0x121ff(%rip), %rax     # 0x15350
sarq $0x4, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rcx, %rax
movq %rax, 0x60(%rsp)
leaq 0x121a9(%rip), %rdi     # 0x15318
movq %r14, %rsi
movq %rbx, %rdx
callq 0x8030
leaq 0x121cf(%rip), %rdi     # 0x15350
movq %r14, %rsi
callq 0x5e50
movq %rbx, %rdi
leaq 0xbf1f(%rip), %rsi      # 0xf0b2
movq %r15, %rdx
callq 0x5f2b
movq %r14, %rdi
movq %rbx, %rsi
callq 0x22e0
movq 0x60(%rsp), %rdi
leaq 0x70(%rsp), %rax
cmpq %rax, %rdi
je 0x31c2
movq 0x70(%rsp), %rsi
incq %rsi
callq 0x2260
movq 0x20(%rsp), %r14
testq %r14, %r14
je 0x31e9
movq 0x18(%rsp), %r12
xorl %ebx, %ebx
movsbl (%r12,%rbx), %edi
callq 0x2410
movb %al, (%r12,%rbx)
incq %rbx
cmpq %rbx, %r14
jne 0x31d3
movq 0x12168(%rip), %rax     # 0x15358
subq 0x12159(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, 0x40(%rsp)
movw $0x0, 0x38(%rsp)
leaq 0x12105(%rip), %rdi     # 0x15318
movq %r13, %r12
movq %r13, %rsi
callq 0x7f18
testq %rax, %rax
leaq 0x60(%rsp), %rbx
leaq 0x1209b(%rip), %r14     # 0x152c8
jne 0x325a
movl 0x40(%rsp), %eax
movl %eax, 0x60(%r15)
leaq 0x120da(%rip), %rdi     # 0x15318
movq %r12, %rsi
leaq 0x40(%rsp), %rdx
callq 0x837a
leaq 0x120fe(%rip), %rdi     # 0x15350
movq %r12, %rsi
callq 0x5e50
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x3276
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x12083(%rip), %rdi     # 0x15300
movq %r15, %rsi
callq 0x5fb4
movq %r14, %rdi
movq %r15, %rsi
leaq 0x4c(%rsp), %rdx
callq 0x837a
addq $0x68, %r15
cmpq %rbp, %r15
jne 0x2fe0
movq 0x88(%rsp), %rbx
movq 0x90(%rsp), %r13
cmpq %r13, %rbx
je 0x34fa
addq $0x28, %rbx
leaq -0x28(%rbx), %rbp
cmpb $0x1, 0x11f96(%rip)     # 0x15260
je 0x3496
leaq -0x8(%rbx), %r14
movb -0x8(%rbx), %al
testb %al, %al
je 0x3314
andb $0xf, %al
cmpb $0x2, %al
jne 0x3383
movslq (%rbx), %rax
movslq 0xb8(%rsp,%rax,4), %rax
cmpq $-0x1, %rax
je 0x3cb0
movl %eax, (%rbx)
movq 0x11ffd(%rip), %rcx     # 0x15300
imulq $0x68, %rax, %rax
movl 0x38(%rcx,%rax), %edx
subl 0x30(%rcx,%rax), %edx
addl %edx, -0x4(%rbx)
jmp 0x3389
leaq 0x11ffd(%rip), %rdi     # 0x15318
movq %rbp, %rsi
callq 0x7f18
testq %rax, %rax
je 0x34a3
movslq 0x28(%rax), %rax
leaq (%rax,%rax,2), %r12
shlq $0x4, %r12
addq 0x12011(%rip), %r12     # 0x15350
movq %rbp, %rdi
movq %r12, %rsi
callq 0x2160
movl 0x28(%r12), %eax
movl %eax, 0x8(%r14)
movq 0x20(%r12), %rax
movq %rax, (%r14)
cmpq $0x0, 0x10(%rsp)
je 0x3480
cmpb $0x0, (%r14)
jne 0x3480
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
callq 0x8b28
jmp 0x3480
movl $0xffffffff, (%rbx)     # imm = 0xFFFFFFFF
movb -0x7(%rbx), %al
notb %al
testb $0x3, %al
jne 0x3480
leaq 0x11f7b(%rip), %rdi     # 0x15318
movq %rbp, %rsi
callq 0x7f18
testq %rax, %rax
je 0x3404
movslq 0x28(%rax), %rax
movq 0x11f9b(%rip), %r12     # 0x15350
leaq (%rax,%rax,2), %r15
shlq $0x4, %r15
leaq (%r12,%r15), %rdi
movb 0x20(%r12,%r15), %al
testb %al, %al
je 0x3445
cmpb (%r14), %al
jne 0x33ea
movb 0x21(%rdi), %al
cmpb -0x7(%rbx), %al
jne 0x33ea
movl 0x28(%rdi), %eax
cmpl (%rbx), %eax
jne 0x33ea
movl 0x24(%rdi), %eax
cmpl -0x4(%rbx), %eax
je 0x3480
movq (%rbp), %rsi
leaq 0xbdbd(%rip), %rdi      # 0xf1b2
xorl %eax, %eax
callq 0x2290
incl 0x11eb6(%rip)           # 0x152b8
jmp 0x3480
movq 0x11f4d(%rip), %rax     # 0x15358
subq 0x11f3e(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, 0x18(%rsp)
leaq 0x11ef1(%rip), %rdi     # 0x15318
movq %rbp, %rsi
leaq 0x18(%rsp), %rdx
callq 0x8d0a
leaq 0x11f15(%rip), %rdi     # 0x15350
movq %rbp, %rsi
callq 0x5fe6
jmp 0x3480
movq %rbp, %rsi
callq 0x2160
leaq (%r12,%r15), %rax
addq $0x20, %rax
movl 0x8(%r14), %ecx
movl %ecx, 0x8(%rax)
movq (%r14), %rcx
movq %rcx, (%rax)
leaq 0x11eff(%rip), %rdi     # 0x15368
movq %rbp, %rsi
callq 0x8e3e
leaq 0x11ef0(%rip), %rdi     # 0x15368
movq %rax, %rsi
callq 0x8ee6
leaq 0x30(%rbx), %rax
addq $0x8, %rbx
cmpq %r13, %rbx
movq %rax, %rbx
jne 0x32bf
jmp 0x34fa
movq %rbp, %rdi
callq 0x2480
jmp 0x32d0
movq 0x11eae(%rip), %rax     # 0x15358
subq 0x11e9f(%rip), %rax     # 0x15350
shrq $0x4, %rax
imull $0xaaaaaaab, %eax, %eax # imm = 0xAAAAAAAB
movl %eax, (%rbx)
leaq 0x11e54(%rip), %rdi     # 0x15318
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x837a
leaq 0x11e7a(%rip), %rdi     # 0x15350
movq %rbp, %rsi
callq 0x5fe6
leaq 0x11e83(%rip), %rdi     # 0x15368
movq %rbp, %rsi
callq 0x8b28
movq %rbp, %rdi
callq 0x24c9
jmp 0x335b
movl $0x98, %eax
addq 0x11dfa(%rip), %rax     # 0x15300
movq %rax, 0x58(%rsp)
movq 0x50(%rsp), %rax
movq (%rax), %r13
movl $0x1, %r14d
leaq 0x28(%rsp), %rbx
leaq 0xf(%rsp), %r15
movzbl (%r13), %ecx
leaq 0x1(%r13), %r12
movb %cl, 0xf(%rsp)
testq %rcx, %rcx
je 0x3563
cmpb $-0x11, %cl
ja 0x3570
movq 0x58(%rsp), %rdi
movq 0x8(%rdi), %rsi
addq %r12, %rcx
movq %r12, %rdx
callq 0x9014
movzbl 0xf(%rsp), %eax
addq %rax, %r12
movl $0x7, %ebp
movq %r12, %r13
jmp 0x3b95
movq %r12, %r13
movl $0x1, %ebp
jmp 0x3b95
xorl %ebp, %ebp
leal -0xf0(%rcx), %eax
cmpl $0x5, %eax
ja 0x355b
leaq 0xbaac(%rip), %rdx      # 0xf030
movslq (%rdx,%rax,4), %rax
addq %rdx, %rax
jmpq *%rax
xorps %xmm0, %xmm0
movups %xmm0, (%rbx)
xorl %eax, %eax
movq %rax, 0x10(%rbx)
movq %rax, 0x18(%rsp)
movl $0x0, 0x1f(%rsp)
cmpl $0xf4, %ecx
sete 0x21(%rsp)
movq %r14, 0x80(%rsp)
movl %r14d, 0x18(%rsp)
movq 0x58(%rsp), %rdi
movq 0x8(%rdi), %rsi
movl (%rdi), %eax
movl %esi, %ecx
subl %eax, %ecx
movl %ecx, 0x1c(%rsp)
movzbl (%r12), %edx
movb %dl, 0x20(%rsp)
movb $0x0, 0x60(%rsp)
leaq 0x60(%rsp), %rbp
movq %rbp, %rcx
callq 0x9226
addq $0x2, %r13
xorl %r14d, %r14d
movq %r13, %r12
movzbl (%r12), %eax
leaq 0x1(%r12), %r13
movb %al, 0xf(%rsp)
leal -0x14(%rax), %ecx
cmpl $0x10, %ecx
jae 0x361f
decl %r14d
movq %rbx, %rdi
movq %r15, %rsi
callq 0x60ce
movq %r13, %r12
jmp 0x35f6
cmpl $0xc, %eax
ja 0x3bd2
movl %eax, %eax
leaq 0xba17(%rip), %rcx      # 0xf048
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rbx, %rdi
movq %r15, %rsi
callq 0x60ce
movq %r13, %r12
jmp 0x35f6
movl 0x1(%r12), %eax
movl %eax, 0x60(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
movq %rbp, %rdx
callq 0x6048
addq $0x5, %r12
incl %r14d
jmp 0x35f6
movzwl 0x1(%r12), %ecx
movq 0x88(%rsp), %rax
movq 0x90(%rsp), %rdx
subq %rax, %rdx
sarq $0x4, %rdx
movabsq $-0x5555555555555555, %rsi # imm = 0xAAAAAAAAAAAAAAAB
imulq %rsi, %rdx
cmpq %rcx, %rdx
jbe 0x3c10
incl %r14d
addq $0x3, %r12
leaq (%rcx,%rcx,2), %rcx
shll $0x4, %ecx
leaq (%rax,%rcx), %r15
movzbl 0x20(%rax,%rcx), %eax
andl $0xf, %eax
cmpl $0x2, %eax
je 0x3771
cmpl $0x1, %eax
je 0x3742
testl %eax, %eax
jne 0x3c2f
movq 0x30(%rsp), %r13
cmpq 0x38(%rsp), %r13
je 0x38a2
movl 0x28(%r15), %eax
movq $0x1, (%r13)
movl %eax, 0x8(%r13)
addq $0xc, %r13
movq %r13, 0x30(%rsp)
leaq 0xf(%rsp), %r15
jmp 0x3a9e
movzbl 0x1(%r12), %eax
movl 0x2(%r12), %ecx
movl %ecx, 0x60(%rsp)
movl 0xb8(%rsp,%rax,4), %eax
movl %eax, 0x4c(%rsp)
testl %eax, %eax
js 0x3bf1
movq %rbx, %rdi
movq %r15, %rsi
movq %rbp, %rdx
leaq 0x4c(%rsp), %rcx
callq 0x608a
incl %r14d
addq $0x6, %r12
jmp 0x35f6
movq %r15, 0x10(%rsp)
movq 0x30(%rsp), %r13
cmpq 0x38(%rsp), %r13
je 0x37ae
movq 0x10(%rsp), %rax
movl 0x24(%rax), %eax
movl $0x2, (%r13)
movl %eax, 0x4(%r13)
movl $0x0, 0x8(%r13)
jmp 0x379b
movq %r15, 0x10(%rsp)
movq 0x30(%rsp), %r13
cmpq 0x38(%rsp), %r13
je 0x3828
movq 0x10(%rsp), %rax
movq 0x24(%rax), %rax
movl $0x3, (%r13)
movq %rax, 0x4(%r13)
addq $0xc, %r13
movq %r13, 0x30(%rsp)
leaq 0xf(%rsp), %r15
jmp 0x35f6
movq 0x28(%rsp), %rax
movq %r13, %rbp
movq %rax, 0x50(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c5a
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 0x3920
movq %rbx, %rdi
movq %rsi, %r15
xorl %edx, %edx
callq 0x88c4
movq %r15, %rsi
jmp 0x3922
movq 0x28(%rsp), %rax
movq %r13, %rbp
movq %rax, 0x50(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c66
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 0x3977
movq %rbx, %rdi
movq %rsi, %r15
xorl %edx, %edx
callq 0x88c4
movq %r15, %rsi
jmp 0x3979
movq 0x28(%rsp), %rax
movq %r13, %rbp
movq %rax, 0x50(%rsp)
subq %rax, %rbp
movabsq $0x7ffffffffffffff8, %rax # imm = 0x7FFFFFFFFFFFFFF8
cmpq %rax, %rbp
je 0x3c4e
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, 0x10(%rsp)
je 0x3a12
movq %rbx, %rdi
xorl %edx, %edx
callq 0x88c4
movq 0x10(%rsp), %rsi
jmp 0x3a14
xorl %eax, %eax
leaq (,%rbp,2), %rdx
addq %rbp, %rdx
movq 0x10(%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 0x50(%rsp), %rdi
cmpq %r13, %rdi
je 0x39c6
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 %r13, %rdx
jne 0x395b
jmp 0x39c6
xorl %eax, %eax
leaq (,%rbp,2), %rdx
addq %rbp, %rdx
movq 0x10(%rsp), %rcx
movq 0x24(%rcx), %rcx
movl $0x3, (%rax,%rdx,4)
movq %rcx, 0x4(%rax,%rdx,4)
movq %rax, %rbp
movq 0x50(%rsp), %rdi
cmpq %r13, %rdi
je 0x39c6
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 %r13, %rdx
jne 0x39ac
testq %rdi, %rdi
leaq 0xf(%rsp), %r15
je 0x39ed
movq %rsi, 0x10(%rsp)
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
movq %rax, %r13
callq 0x2260
movq %r13, %rax
movq 0x10(%rsp), %rsi
addq $0xc, %rbp
movq %rax, 0x28(%rsp)
movq %rbp, 0x30(%rsp)
leaq (%rsi,%rsi,2), %rcx
leaq (%rax,%rcx,4), %rax
movq %rax, 0x38(%rsp)
leaq 0x60(%rsp), %rbp
jmp 0x35f6
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 0x50(%rsp), %rdi
cmpq %r13, %rdi
je 0x3a5c
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 %r13, %rdx
jne 0x3a42
testq %rdi, %rdi
leaq 0xf(%rsp), %r15
je 0x3a7e
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
movq %rax, %r13
callq 0x2260
movq %r13, %rax
movq 0x10(%rsp), %rsi
addq $0xc, %rbp
movq %rax, 0x28(%rsp)
movq %rbp, 0x30(%rsp)
leaq (%rsi,%rsi,2), %rcx
leaq (%rax,%rcx,4), %rax
movq %rax, 0x38(%rsp)
leaq 0x60(%rsp), %rbp
movb $0x1, 0x22(%rsp)
jmp 0x35f6
cmpl $0x1, %r14d
je 0x3ac4
movl $0x1, %edi
leaq 0x18(%rsp), %rsi
leaq 0xb7c4(%rip), %rdx      # 0xf283
callq 0x6108
movl 0x80(%rsp), %eax
movq 0x1182e(%rip), %rcx     # 0x15300
imulq $0x68, %rax, %rax
leaq (%rcx,%rax), %rdi
addq $0x48, %rdi
leaq 0x18(%rsp), %rsi
callq 0x6de0
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x3aff
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
xorl %ebp, %ebp
movq 0x80(%rsp), %r14
jmp 0x3b95
movzbl 0x1(%r13), %eax
movslq 0xb8(%rsp,%rax,4), %r14
testq %r14, %r14
jle 0x3c72
movq 0x117dd(%rip), %rcx     # 0x15308
movq 0x117ce(%rip), %rax     # 0x15300
subq %rax, %rcx
sarq $0x3, %rcx
movabsq $0x4ec4ec4ec4ec4ec5, %rdx # imm = 0x4EC4EC4EC4EC4EC5
imulq %rdx, %rcx
cmpq %r14, %rcx
jbe 0x3c72
addq $0x2, %r13
imulq $0x68, %r14, %rcx
addq %rcx, %rax
addq $0x30, %rax
movq %rax, 0x58(%rsp)
jmp 0x3b95
movzwl 0x1(%r13), %eax
addq %rax, %r13
addq $0x3, %r13
jmp 0x3b95
movzwl 0x1(%r13), %edx
movq 0x58(%rsp), %rdi
movq 0x8(%rdi), %rsi
movb $0x0, 0x18(%rsp)
leaq 0x18(%rsp), %rcx
callq 0x9226
addq $0x3, %r13
testl %ebp, %ebp
je 0x3523
cmpl $0x7, %ebp
je 0x3523
leaq 0x88(%rsp), %rdi
callq 0x5ec4
leaq 0xa0(%rsp), %rdi
callq 0x5e20
addq $0x4b8, %rsp            # imm = 0x4B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb688(%rip), %rdi      # 0xf261
leaq 0xb4ec(%rip), %rsi      # 0xf0cc
leaq 0xb4ee(%rip), %rcx      # 0xf0d5
movl $0x2e1, %edx            # imm = 0x2E1
callq 0x21c0
leaq 0xb657(%rip), %rdi      # 0xf24f
leaq 0xb4cd(%rip), %rsi      # 0xf0cc
leaq 0xb4cf(%rip), %rcx      # 0xf0d5
movl $0x2c1, %edx            # imm = 0x2C1
callq 0x21c0
leaq 0xb5fd(%rip), %rdi      # 0xf214
leaq 0xb4ae(%rip), %rsi      # 0xf0cc
leaq 0xb4b0(%rip), %rcx      # 0xf0d5
movl $0x2a6, %edx            # imm = 0x2A6
callq 0x21c0
leaq 0xb5fc(%rip), %rdi      # 0xf232
leaq 0xb48f(%rip), %rsi      # 0xf0cc
leaq 0xb491(%rip), %rcx      # 0xf0d5
movl $0x2b8, %edx            # imm = 0x2B8
callq 0x21c0
leaq 0xbbd2(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xbbc6(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xbbba(%rip), %rdi      # 0xf827
callq 0x2150
leaq 0xb54c(%rip), %rdi      # 0xf1c5
leaq 0xb44c(%rip), %rsi      # 0xf0cc
leaq 0xb44e(%rip), %rcx      # 0xf0d5
movl $0x27e, %edx            # imm = 0x27E
callq 0x21c0
leaq 0xb420(%rip), %rdi      # 0xf0b8
leaq 0xb42d(%rip), %rsi      # 0xf0cc
leaq 0xb42f(%rip), %rcx      # 0xf0d5
movl $0x209, %edx            # imm = 0x209
callq 0x21c0
leaq 0xb4e5(%rip), %rdi      # 0xf19c
leaq 0xb40e(%rip), %rsi      # 0xf0cc
leaq 0xb410(%rip), %rcx      # 0xf0d5
movl $0x23c, %edx            # imm = 0x23C
callq 0x21c0
leaq 0xb528(%rip), %rdi      # 0xf1fe
leaq 0xb3ef(%rip), %rsi      # 0xf0cc
leaq 0xb3f1(%rip), %rcx      # 0xf0d5
movl $0x285, %edx            # imm = 0x285
callq 0x21c0
jmp 0x3cfd
movq %rax, %rbx
jmp 0x3d67
jmp 0x3cfd
jmp 0x3cfd
jmp 0x3cfd
jmp 0x3d37
movq %rax, %rbx
movq 0x18(%rsp), %rdi
leaq 0x28(%rsp), %rax
cmpq %rax, %rdi
je 0x3d5a
movq 0x28(%rsp), %rsi
incq %rsi
jmp 0x3d55
jmp 0x3d37
jmp 0x3d37
jmp 0x3d40
jmp 0x3d37
jmp 0x3d37
jmp 0x3d37
jmp 0x3d40
jmp 0x3d37
jmp 0x3d40
jmp 0x3d40
jmp 0x3d40
jmp 0x3d37
jmp 0x3d40
jmp 0x3d40
jmp 0x3d40
movq %rax, %rbx
jmp 0x3d5a
jmp 0x3d40
jmp 0x3d40
movq %rax, %rbx
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
je 0x3d5a
movq 0x38(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
leaq 0x88(%rsp), %rdi
callq 0x5ec4
leaq 0xa0(%rsp), %rdi
callq 0x5e20
movq %rbx, %rdi
callq 0x23c0