// File: /workspace/github_cpp_makefile_star2_O1/ksherlock[P]wdc-utils/omf.cpp
// Function: add_relocs(std::vector<unsigned char, std::allocator<unsigned char>>&, unsigned long, omf::segment&, bool, bool)
uint32_t add_relocs(std::vector<uint8_t> &data, size_t data_offset, omf::segment &seg, bool compress, bool super) {

	std::array< optional<super_helper>, 38 > ss;


	uint32_t reloc_size = 0;

	for (auto &r : seg.relocs) {

		if (compress && r.can_compress()) {

			if (super) {
				if (r.shift == 0 && r.size == 2) {
					constexpr int n = SUPER_RELOC2;

					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.value;
					for (int i = 0; i < 2; ++i, value >>= 8)
						data[data_offset + r.offset + i] = value; 
					continue;
				}

				// sreloc 3 is for 3 bytes.  however 4 bytes is also ok since 
				// it's 24-bit address space.
				if (r.shift == 0 && (r.size == 2 || r.size == 3))
				{
					constexpr int n = SUPER_RELOC3;

					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.value;
					for (int i = 0; i < 3; ++i, value >>= 8)
						data[data_offset + r.offset + i] = value; 
					continue;	
				}

				// if size == 2 && shift == -16, -> SUPER INTERSEG 
				if (seg.segnum <= 12 && r.shift == 0xf0 && r.size == 2) {

					int n = SUPER_INTERSEG24 + seg.segnum;
					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.value;
					for (int i = 0; i < 2; ++i, value >>= 8)
						data[data_offset + r.offset + i] = value; 
					continue;
				}
			}

			push(data, (uint8_t)omf::cRELOC);
			push(data, (uint8_t)r.size);
			push(data, (uint8_t)r.shift);
			push(data, (uint16_t)r.offset);
			push(data, (uint16_t)r.value);
			reloc_size += 7;
		} else {
			push(data, (uint8_t)omf::RELOC);
			push(data, (uint8_t)r.size);
			push(data, (uint8_t)r.shift);
			push(data, (uint32_t)r.offset);
			push(data, (uint32_t)r.value);
			reloc_size += 11;
		}
	}

	for (const auto &r : seg.intersegs) {
		if (compress && r.can_compress()) {

			if (super) {

				if (r.shift == 0 && r.size == 3) {
					constexpr int n = SUPER_INTERSEG1;
					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.segment_offset;

					data[data_offset + r.offset + 0] = value; value >>= 8;
					data[data_offset + r.offset + 1] = value; value >>= 8;
					data[data_offset + r.offset + 2] = r.segment;
					continue;
				}


				if (r.shift == 0 && r.size == 2 && r.segment <= 12) {

					int n = SUPER_INTERSEG12 + r.segment;
					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.segment_offset;
					for (int i = 0; i < 2; ++i, value >>= 8)
						data[data_offset + r.offset + i] = value; 
					continue;
				}

				if (r.shift == 0xf0 && r.size == 2 && r.segment <= 12) {

					int n = SUPER_INTERSEG24 + r.segment;
					auto &sr = ss[n];
					if (!sr) sr.emplace();
					sr->append(r.offset);

					uint32_t value = r.segment_offset;
					for (int i = 0; i < 2; ++i, value >>= 8)
						data[data_offset + r.offset + i] = value; 
					continue;
				}
			}


			push(data, (uint8_t)omf::cINTERSEG);
			push(data, (uint8_t)r.size);
			push(data, (uint8_t)r.shift);
			push(data, (uint16_t)r.offset);
			push(data, (uint8_t)r.segment);
			push(data, (uint16_t)r.segment_offset);
			reloc_size += 8;
		} else {
			push(data, (uint8_t)omf::INTERSEG);
			push(data, (uint8_t)r.size);
			push(data, (uint8_t)r.shift);
			push(data, (uint32_t)r.offset);
			push(data, (uint16_t)r.file);
			push(data, (uint16_t)r.segment);
			push(data, (uint32_t)r.segment_offset);
			reloc_size += 15;
		}
	}


	for (int i = 0; i < ss.size(); ++i) {
		auto &s = ss[i];
		if (!s) continue;

		auto tmp = s->data();
		if (tmp.empty()) continue;

		reloc_size += tmp.size() + 6;
		data.push_back(omf::SUPER);
		push(data, ((uint32_t)tmp.size() + 1));
		data.push_back(i);

		data.insert(data.end(), tmp.begin(), tmp.end());
	}

	return reloc_size;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x628, %rsp            # imm = 0x628
movl %r8d, 0x28(%rsp)
movl %ecx, 0x2c(%rsp)
movq %rsi, %rbp
movq %rdi, %r14
xorl %eax, %eax
movb $0x0, 0x38(%rsp,%rax)
addq $0x28, %rax
cmpq $0x5f0, %rax            # imm = 0x5F0
jne 0xc3c5
movq 0x80(%rdx), %r12
movq %rdx, 0x30(%rsp)
movq 0x88(%rdx), %r13
xorl %ebx, %ebx
cmpq %r13, %r12
je 0xc62e
movq %rbx, %r15
cmpb $0x0, 0x2c(%rsp)
je 0xc48c
cmpl $0xffff, 0x4(%r12)      # imm = 0xFFFF
ja 0xc48c
cmpl $0xffff, 0x8(%r12)      # imm = 0xFFFF
ja 0xc48c
cmpb $0x0, 0x28(%rsp)
je 0xc5ad
movb (%r12), %dl
movb 0x1(%r12), %al
movl %edx, %ecx
xorb $0x2, %cl
movl %eax, %esi
orb %cl, %sil
jne 0xc4dd
cmpb $0x0, 0x38(%rsp)
jne 0xc457
leaq 0x40(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movups %xmm0, (%rax)
movb $0x1, 0x38(%rsp)
movl 0x4(%r12), %esi
leaq 0x40(%rsp), %rdi
callq 0xd550
movq %r15, %rbx
movl 0x8(%r12), %eax
xorl %ecx, %ecx
movl 0x4(%r12), %edx
addq (%r14), %rdx
addq %rbp, %rdx
movb %al, (%rcx,%rdx)
incq %rcx
shrl $0x8, %eax
cmpq $0x1, %rcx
je 0xc470
jmp 0xc4d4
movq %r14, %rdi
movl $0xe2, %esi
callq 0xc228
movzbl (%r12), %esi
movq %r14, %rdi
callq 0xc228
movzbl 0x1(%r12), %esi
movq %r14, %rdi
callq 0xc228
movl 0x4(%r12), %esi
movq %r14, %rdi
callq 0xc27b
movl 0x8(%r12), %esi
movq %r14, %rdi
callq 0xc27b
movq %r15, %rbx
addl $0xb, %ebx
addq $0xc, %r12
jmp 0xc3eb
andb $-0x2, %dl
xorb $0x2, %dl
orb %al, %dl
jne 0xc539
cmpb $0x0, 0x60(%rsp)
jne 0xc502
leaq 0x68(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movups %xmm0, (%rax)
movb $0x1, 0x60(%rsp)
movl 0x4(%r12), %esi
leaq 0x68(%rsp), %rdi
callq 0xd550
movq %r15, %rbx
movl 0x8(%r12), %eax
movq $-0x3, %rcx
movl 0x4(%r12), %edx
addq (%r14), %rdx
addq %rbp, %rdx
movb %al, 0x3(%rcx,%rdx)
shrl $0x8, %eax
incq %rcx
jne 0xc520
jmp 0xc4d4
movq 0x30(%rsp), %rdx
movzwl (%rdx), %edx
cmpq $0xd, %rdx
setb %sil
xorb $-0x10, %al
orb %cl, %al
sete %al
andb %sil, %al
cmpb $0x1, %al
jne 0xc5ad
leaq (%rdx,%rdx,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x420, %rbx            # imm = 0x420
cmpb $0x0, (%rbx)
jne 0xc573
movq %rbx, %rdi
callq 0xd51e
addq $0x8, %rbx
movl 0x4(%r12), %esi
movq %rbx, %rdi
callq 0xd550
movl 0x8(%r12), %eax
xorl %ecx, %ecx
movq %r15, %rbx
movl 0x4(%r12), %edx
addq (%r14), %rdx
addq %rbp, %rdx
movb %al, (%rcx,%rdx)
incq %rcx
shrl $0x8, %eax
cmpq $0x1, %rcx
je 0xc58e
jmp 0xc4d4
movq %r14, %rdi
movl $0xf5, %esi
callq 0xc228
movzbl (%r12), %esi
movq %r14, %rdi
callq 0xc228
movzbl 0x1(%r12), %esi
movq %r14, %rdi
callq 0xc228
movl 0x4(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd76c
movl 0x8(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd76c
movq %r15, %rbx
addl $0x7, %ebx
jmp 0xc4d4
movq 0x30(%rsp), %rax
movq 0x68(%rax), %r12
movq 0x70(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq %rax, %r12
je 0xc931
leaq 0x10(%rsp), %r13
movq %rbx, %r15
cmpb $0x0, 0x2c(%rsp)
je 0xc727
cmpw $0x1, 0x8(%r12)
jne 0xc727
movzwl 0xa(%r12), %eax
cmpl $0xff, %eax
ja 0xc727
cmpl $0xffff, 0x4(%r12)      # imm = 0xFFFF
ja 0xc727
cmpl $0xffff, 0xc(%r12)      # imm = 0xFFFF
ja 0xc727
cmpb $0x0, 0x28(%rsp)
je 0xc8aa
movb (%r12), %cl
movb 0x1(%r12), %dl
movl %ecx, %esi
xorb $0x3, %sil
orb %dl, %sil
jne 0xc7cb
cmpb $0x0, 0x88(%rsp)
jne 0xc6df
leaq 0x90(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movups %xmm0, (%rax)
movb $0x1, 0x88(%rsp)
movl 0x4(%r12), %esi
leaq 0x90(%rsp), %rdi
callq 0xd550
movq %r15, %rbx
movl 0x4(%r12), %ecx
movl 0xc(%r12), %eax
addq (%r14), %rcx
movb %al, (%rbp,%rcx)
movl 0x4(%r12), %ecx
addq (%r14), %rcx
movb %ah, 0x1(%rbp,%rcx)
movb 0xa(%r12), %al
movl 0x4(%r12), %ecx
addq (%r14), %rcx
movb %al, 0x2(%rbp,%rcx)
jmp 0xc7b7
movq %r14, %rdi
movl $0xe3, %esi
callq 0xc228
movzbl (%r12), %esi
movq %r14, %rdi
callq 0xc228
movzbl 0x1(%r12), %esi
movq %r14, %rdi
callq 0xc228
movl 0x4(%r12), %esi
movq %r14, %rdi
callq 0xc27b
movzwl 0x8(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movzwl 0xa(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movl 0xc(%r12), %esi
movq %r14, %rdi
callq 0xc27b
movq %r15, %rbx
addl $0xf, %ebx
addq $0x10, %r12
cmpq 0x30(%rsp), %r12
jne 0xc64e
jmp 0xc931
xorb $0x2, %cl
movl %edx, %esi
orb %cl, %sil
sete %sil
cmpw $0xd, %ax
setb %dil
andb %sil, %dil
cmpb $0x1, %dil
jne 0xc83e
leaq (%rax,%rax,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x240, %rbx            # imm = 0x240
cmpb $0x0, (%rbx)
jne 0xc804
movq %rbx, %rdi
callq 0xd51e
addq $0x8, %rbx
movl 0x4(%r12), %esi
movq %rbx, %rdi
callq 0xd550
movq %r15, %rbx
movl 0xc(%r12), %eax
xorl %ecx, %ecx
movl 0x4(%r12), %edx
addq (%r14), %rdx
addq %rbp, %rdx
movb %al, (%rcx,%rdx)
incq %rcx
shrl $0x8, %eax
cmpq $0x1, %rcx
je 0xc81f
jmp 0xc7b7
xorb $-0x10, %dl
orb %cl, %dl
sete %cl
cmpw $0xd, %ax
setb %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0xc8aa
leaq (%rax,%rax,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x420, %rbx            # imm = 0x420
cmpb $0x0, (%rbx)
jne 0xc870
movq %rbx, %rdi
callq 0xd51e
addq $0x8, %rbx
movl 0x4(%r12), %esi
movq %rbx, %rdi
callq 0xd550
movl 0xc(%r12), %eax
xorl %ecx, %ecx
movq %r15, %rbx
movl 0x4(%r12), %edx
addq (%r14), %rdx
addq %rbp, %rdx
movb %al, (%rcx,%rdx)
incq %rcx
shrl $0x8, %eax
cmpq $0x1, %rcx
je 0xc88b
jmp 0xc7b7
movq %r14, %rdi
movl $0xf6, %esi
callq 0xc228
movzbl (%r12), %esi
movq %r14, %rdi
callq 0xc228
movzbl 0x1(%r12), %esi
movq %r14, %rdi
callq 0xc228
movl 0x4(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movzbl 0xa(%r12), %esi
movq %r14, %rdi
callq 0xc228
movl 0xc(%r12), %ebx
movb %bl, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movb %bh, 0x10(%rsp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xd76c
movq %r15, %rbx
addl $0x8, %ebx
jmp 0xc7b7
leaq 0x40(%rsp), %r15
xorl %ebp, %ebp
cmpb $0x1, -0x8(%r15)
jne 0xc9cb
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
callq 0x8668
movq 0x10(%rsp), %r13
movq 0x18(%rsp), %r12
cmpq %r12, %r13
je 0xc9b4
movb $-0x9, 0xf(%rsp)
movq %r14, %rdi
leaq 0xf(%rsp), %rsi
callq 0xd76c
movl 0x18(%rsp), %esi
subl 0x10(%rsp), %esi
incl %esi
movq %r14, %rdi
callq 0xc27b
movb %bpl, 0xf(%rsp)
movq %r14, %rdi
leaq 0xf(%rsp), %rsi
callq 0xd76c
movq 0x8(%r14), %rsi
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rcx
movq %r14, %rdi
callq 0xdcfa
subl %r13d, %r12d
addl %r12d, %ebx
addl $0x6, %ebx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xc9cb
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
incq %rbp
addq $0x28, %r15
cmpq $0x26, %rbp
jne 0xc938
movl $0x5c8, %r14d           # imm = 0x5C8
cmpb $0x1, 0x38(%rsp,%r14)
jne 0xca07
movq 0x40(%rsp,%r14), %rdi
testq %rdi, %rdi
je 0xca01
movq 0x50(%rsp,%r14), %rsi
subq %rdi, %rsi
callq 0x2260
movb $0x0, 0x38(%rsp,%r14)
addq $-0x28, %r14
cmpq $-0x28, %r14
jne 0xc9e2
movl %ebx, %eax
addq $0x628, %rsp            # imm = 0x628
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xca57
jmp 0xca57
jmp 0xca57
jmp 0xca57
jmp 0xca57
jmp 0xca57
jmp 0xca37
jmp 0xca37
jmp 0xca37
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xca5a
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
jmp 0xca5a
jmp 0xca57
jmp 0xca57
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0xd638
movq %rbx, %rdi
callq 0x23c0