// File: /workspace/github_cpp_makefile_star2_O3/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, 0x30(%rsp)
movl %ecx, 0x34(%rsp)
movq %rdx, 0x28(%rsp)
movq %rsi, %rbp
movq %rdi, %r12
leaq 0x38(%rsp), %rax
xorl %ecx, %ecx
movdqa 0x381d(%rip), %xmm0     # 0xf9b0
movdqa 0x3825(%rip), %xmm1     # 0xf9c0
movdqa 0x382d(%rip), %xmm2     # 0xf9d0
movdqa 0x3835(%rip), %xmm3     # 0xf9e0
movdqa 0x383d(%rip), %xmm6     # 0xf9f0
pshufd $0xa0, %xmm6, %xmm4     # xmm4 = xmm6[0,0,2,2]
movdqa 0x3840(%rip), %xmm5     # 0xfa00
pshufd $0xf5, %xmm6, %xmm6     # xmm6 = xmm6[1,1,3,3]
movq %rcx, %xmm7
pshufd $0x44, %xmm7, %xmm7     # xmm7 = xmm7[0,1,0,1]
movdqa %xmm7, %xmm8
por %xmm3, %xmm8
pxor %xmm5, %xmm8
pshufd $0xa0, %xmm8, %xmm9     # xmm9 = xmm8[0,0,2,2]
movdqa %xmm4, %xmm10
pcmpgtd %xmm9, %xmm10
pshufd $0xf5, %xmm8, %xmm8     # xmm8 = xmm8[1,1,3,3]
pcmpeqd %xmm6, %xmm8
pand %xmm10, %xmm8
pshuflw $0xe8, %xmm8, %xmm9     # xmm9 = xmm8[0,2,2,3,4,5,6,7]
packssdw %xmm9, %xmm9
movd %xmm9, %edx
testb $0x1, %dl
je 0xc216
movb $0x0, (%rax)
packssdw %xmm8, %xmm8
packssdw %xmm8, %xmm8
movd %xmm8, %edx
shrl $0x10, %edx
testb $0x1, %dl
je 0xc231
movb $0x0, 0x28(%rax)
movdqa %xmm7, %xmm8
por %xmm2, %xmm8
pxor %xmm5, %xmm8
pshufd $0xa0, %xmm8, %xmm9     # xmm9 = xmm8[0,0,2,2]
movdqa %xmm4, %xmm10
pcmpgtd %xmm9, %xmm10
pshufd $0xf5, %xmm8, %xmm8     # xmm8 = xmm8[1,1,3,3]
pcmpeqd %xmm6, %xmm8
pand %xmm10, %xmm8
packssdw %xmm8, %xmm9
packssdw %xmm9, %xmm9
pextrw $0x2, %xmm9, %edx
testb $0x1, %dl
je 0xc279
movb $0x0, 0x50(%rax)
pshufhw $0x84, %xmm8, %xmm8     # xmm8 = xmm8[0,1,2,3,4,5,4,6]
packssdw %xmm8, %xmm8
pextrw $0x3, %xmm8, %edx
testb $0x1, %dl
je 0xc293
movb $0x0, 0x78(%rax)
movdqa %xmm7, %xmm8
por %xmm1, %xmm8
pxor %xmm5, %xmm8
pshufd $0xa0, %xmm8, %xmm9     # xmm9 = xmm8[0,0,2,2]
movdqa %xmm4, %xmm10
pcmpgtd %xmm9, %xmm10
pshufd $0xf5, %xmm8, %xmm8     # xmm8 = xmm8[1,1,3,3]
pcmpeqd %xmm6, %xmm8
pand %xmm10, %xmm8
pshuflw $0xe8, %xmm8, %xmm9     # xmm9 = xmm8[0,2,2,3,4,5,6,7]
packssdw %xmm9, %xmm9
pextrw $0x4, %xmm9, %edx
testb $0x1, %dl
je 0xc2df
movb $0x0, 0xa0(%rax)
packssdw %xmm8, %xmm8
packssdw %xmm8, %xmm8
pextrw $0x5, %xmm8, %edx
testb $0x1, %dl
je 0xc2fb
movb $0x0, 0xc8(%rax)
por %xmm0, %xmm7
pxor %xmm5, %xmm7
pshufd $0xa0, %xmm7, %xmm8     # xmm8 = xmm7[0,0,2,2]
movdqa %xmm4, %xmm9
pcmpgtd %xmm8, %xmm9
pshufd $0xf5, %xmm7, %xmm7     # xmm7 = xmm7[1,1,3,3]
pcmpeqd %xmm6, %xmm7
pand %xmm9, %xmm7
packssdw %xmm7, %xmm8
packssdw %xmm8, %xmm8
pextrw $0x6, %xmm8, %edx
testb $0x1, %dl
je 0xc33d
movb $0x0, 0xf0(%rax)
pshufhw $0x84, %xmm7, %xmm7     # xmm7 = xmm7[0,1,2,3,4,5,4,6]
packssdw %xmm7, %xmm7
pextrw $0x7, %xmm7, %edx
testb $0x1, %dl
je 0xc357
movb $0x0, 0x118(%rax)
addq $0x8, %rcx
addq $0x140, %rax            # imm = 0x140
cmpq $0x28, %rcx
jne 0xc1c5
movq 0x28(%rsp), %rax
movq 0x80(%rax), %r14
movq 0x88(%rax), %r15
xorl %ebx, %ebx
cmpq %r15, %r14
je 0xc5d6
movq %rbx, %r13
cmpb $0x0, 0x34(%rsp)
je 0xc42c
movl 0x4(%r14), %esi
cmpl $0xffff, %esi           # imm = 0xFFFF
ja 0xc42c
cmpl $0xffff, 0x8(%r14)      # imm = 0xFFFF
ja 0xc42c
cmpb $0x0, 0x30(%rsp)
je 0xc559
movb (%r14), %dl
movb 0x1(%r14), %al
movl %edx, %ecx
xorb $0x2, %cl
movl %eax, %edi
orb %cl, %dil
jne 0xc479
cmpb $0x0, 0x38(%rsp)
jne 0xc3f5
leaq 0x40(%rsp), %rax
pxor %xmm0, %xmm0
movdqu %xmm0, 0x10(%rax)
movdqu %xmm0, (%rax)
movb $0x1, 0x38(%rsp)
movl 0x4(%r14), %esi
leaq 0x40(%rsp), %rdi
callq 0xd508
movq %r13, %rbx
movl 0x8(%r14), %eax
movb $0x1, %cl
xorl %edx, %edx
movl 0x4(%r14), %esi
addq (%r12), %rsi
addq %rbp, %rsi
movb %al, (%rdx,%rsi)
shrl $0x8, %eax
movl $0x1, %edx
testb $0x1, %cl
movl $0x0, %ecx
jne 0xc40a
jmp 0xc470
movq %r12, %rdi
movl $0xe2, %esi
callq 0xbfe4
movzbl (%r14), %esi
movq %r12, %rdi
callq 0xbfe4
movzbl 0x1(%r14), %esi
movq %r12, %rdi
callq 0xbfe4
movl 0x4(%r14), %esi
movq %r12, %rdi
callq 0xc037
movl 0x8(%r14), %esi
movq %r12, %rdi
callq 0xc037
movq %r13, %rbx
addl $0xb, %ebx
addq $0xc, %r14
jmp 0xc380
testb %al, %al
je 0xc4fb
movq 0x28(%rsp), %rdx
movzwl (%rdx), %edx
cmpq $0xd, %rdx
setb %dil
xorb $-0x10, %al
orb %cl, %al
sete %al
andb %dil, %al
cmpb $0x1, %al
jne 0xc559
leaq (%rdx,%rdx,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x420, %rbx            # imm = 0x420
cmpb $0x0, (%rbx)
jne 0xc4bf
movq %rbx, %rdi
callq 0xd4da
movl 0x4(%r14), %esi
addq $0x8, %rbx
movq %rbx, %rdi
callq 0xd508
movl 0x8(%r14), %eax
movb $0x1, %cl
xorl %edx, %edx
movl 0x4(%r14), %esi
addq (%r12), %rsi
addq %rbp, %rsi
movb %al, (%rdx,%rsi)
shrl $0x8, %eax
movl $0x1, %edx
testb $0x1, %cl
movl $0x0, %ecx
jne 0xc4d3
movq %r13, %rbx
jmp 0xc470
andb $-0x2, %dl
cmpb $0x2, %dl
jne 0xc559
cmpb $0x0, 0x60(%rsp)
jne 0xc525
leaq 0x68(%rsp), %rax
pxor %xmm0, %xmm0
movdqu %xmm0, 0x10(%rax)
movdqu %xmm0, (%rax)
movb $0x1, 0x60(%rsp)
movl 0x4(%r14), %esi
leaq 0x68(%rsp), %rdi
callq 0xd508
movl 0x8(%r14), %eax
movq $-0x3, %rcx
movq %r13, %rbx
movl 0x4(%r14), %edx
addq (%r12), %rdx
addq %rbp, %rdx
movb %al, 0x3(%rcx,%rdx)
shrl $0x8, %eax
incq %rcx
jne 0xc53d
jmp 0xc470
movq %r12, %rdi
movl $0xf5, %esi
callq 0xbfe4
movzbl (%r14), %esi
movq %r12, %rdi
callq 0xbfe4
movzbl 0x1(%r14), %esi
movq %r12, %rdi
callq 0xbfe4
movl 0x4(%r14), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd724
movl 0x8(%r14), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
leaq 0x10(%rsp), %rsi
callq 0xd724
movq %r13, %rbx
addl $0x7, %ebx
jmp 0xc470
movq 0x28(%rsp), %rax
movq 0x68(%rax), %r15
movq 0x70(%rax), %rax
movq %rax, 0x28(%rsp)
cmpq %rax, %r15
je 0xc8d5
leaq 0x10(%rsp), %r13
movq %rbx, %r14
cmpb $0x0, 0x34(%rsp)
je 0xc6d3
cmpw $0x1, 0x8(%r15)
sete %cl
movzwl 0xa(%r15), %eax
cmpl $0x100, %eax            # imm = 0x100
setb %dl
movl 0x4(%r15), %esi
cmpl $0x10000, %esi          # imm = 0x10000
setb %dil
andb %cl, %dil
andb %dl, %dil
cmpb $0x1, %dil
jne 0xc6d3
cmpl $0xffff, 0xc(%r15)      # imm = 0xFFFF
ja 0xc6d3
cmpb $0x0, 0x30(%rsp)
je 0xc853
movb (%r15), %cl
movb 0x1(%r15), %dl
movl %ecx, %edi
xorb $0x3, %dil
orb %dl, %dil
jne 0xc771
cmpb $0x0, 0x88(%rsp)
jne 0xc692
leaq 0x90(%rsp), %rax
pxor %xmm0, %xmm0
movdqu %xmm0, 0x10(%rax)
movdqu %xmm0, (%rax)
movb $0x1, 0x88(%rsp)
movl 0x4(%r15), %esi
leaq 0x90(%rsp), %rdi
callq 0xd508
movq %r14, %rbx
movl 0x4(%r15), %ecx
movl 0xc(%r15), %eax
addq (%r12), %rcx
movb %al, (%rbp,%rcx)
movl 0x4(%r15), %ecx
addq (%r12), %rcx
movb %ah, 0x1(%rbp,%rcx)
movb 0xa(%r15), %al
movl 0x4(%r15), %ecx
addq (%r12), %rcx
movb %al, 0x2(%rbp,%rcx)
jmp 0xc75d
movq %r12, %rdi
movl $0xe3, %esi
callq 0xbfe4
movzbl (%r15), %esi
movq %r12, %rdi
callq 0xbfe4
movzbl 0x1(%r15), %esi
movq %r12, %rdi
callq 0xbfe4
movl 0x4(%r15), %esi
movq %r12, %rdi
callq 0xc037
movzwl 0x8(%r15), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movzwl 0xa(%r15), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movl 0xc(%r15), %esi
movq %r12, %rdi
callq 0xc037
movq %r14, %rbx
addl $0xf, %ebx
addq $0x10, %r15
cmpq 0x28(%rsp), %r15
jne 0xc5f6
jmp 0xc8d5
xorb $0x2, %cl
movl %edx, %edi
orb %cl, %dil
jne 0xc7e1
cmpw $0xc, %ax
ja 0xc853
leaq (%rax,%rax,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x240, %rbx            # imm = 0x240
cmpb $0x0, (%rbx)
jne 0xc7a5
movq %rbx, %rdi
callq 0xd4da
movl 0x4(%r15), %esi
addq $0x8, %rbx
movq %rbx, %rdi
callq 0xd508
movl 0xc(%r15), %eax
movb $0x1, %cl
xorl %edx, %edx
movq %r14, %rbx
movl 0x4(%r15), %esi
addq (%r12), %rsi
addq %rbp, %rsi
movb %al, (%rdx,%rsi)
shrl $0x8, %eax
movl $0x1, %edx
testb $0x1, %cl
movl $0x0, %ecx
jne 0xc7bc
jmp 0xc75d
xorb $-0x10, %dl
orb %cl, %dl
sete %cl
cmpw $0xd, %ax
setb %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0xc853
leaq (%rax,%rax,4), %rax
leaq (%rsp,%rax,8), %rbx
addq $0x420, %rbx            # imm = 0x420
cmpb $0x0, (%rbx)
jne 0xc817
movq %rbx, %rdi
callq 0xd4da
movl 0x4(%r15), %esi
addq $0x8, %rbx
movq %rbx, %rdi
callq 0xd508
movl 0xc(%r15), %eax
movb $0x1, %cl
xorl %edx, %edx
movq %r14, %rbx
movl 0x4(%r15), %esi
addq (%r12), %rsi
addq %rbp, %rsi
movb %al, (%rdx,%rsi)
shrl $0x8, %eax
movl $0x1, %edx
testb $0x1, %cl
movl $0x0, %ecx
jne 0xc82e
jmp 0xc75d
movq %r12, %rdi
movl $0xf6, %esi
callq 0xbfe4
movzbl (%r15), %esi
movq %r12, %rdi
callq 0xbfe4
movzbl 0x1(%r15), %esi
movq %r12, %rdi
callq 0xbfe4
movl 0x4(%r15), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movzbl 0xa(%r15), %esi
movq %r12, %rdi
callq 0xbfe4
movl 0xc(%r15), %ebx
movb %bl, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movb %bh, 0x10(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0xd724
movq %r14, %rbx
addl $0x8, %ebx
jmp 0xc75d
leaq 0x40(%rsp), %r14
xorl %r15d, %r15d
cmpb $0x1, -0x8(%r14)
jne 0xc974
leaq 0x10(%rsp), %rdi
movq %r14, %rsi
callq 0x85b4
movq 0x10(%rsp), %rbp
movq 0x18(%rsp), %r13
cmpq %r13, %rbp
je 0xc95f
movb $-0x9, 0xf(%rsp)
movq %r12, %rdi
leaq 0xf(%rsp), %rsi
callq 0xd724
movl 0x18(%rsp), %esi
subl 0x10(%rsp), %esi
incl %esi
movq %r12, %rdi
callq 0xc037
movb %r15b, 0xf(%rsp)
movq %r12, %rdi
leaq 0xf(%rsp), %rsi
callq 0xd724
movq 0x8(%r12), %rsi
movq 0x10(%rsp), %rdx
movq 0x18(%rsp), %rcx
movq %r12, %rdi
callq 0xdcf6
subl %ebp, %r13d
addl %r13d, %ebx
addl $0x6, %ebx
movq 0x10(%rsp), %rbp
testq %rbp, %rbp
je 0xc974
movq 0x20(%rsp), %rsi
subq %rbp, %rsi
movq %rbp, %rdi
callq 0x2260
incq %r15
addq $0x28, %r14
cmpq $0x26, %r15
jne 0xc8dd
movq %rbx, %r14
movl $0x5c8, %ebx            # imm = 0x5C8
cmpb $0x1, 0x38(%rsp,%rbx)
jne 0xc9b0
movq 0x40(%rsp,%rbx), %rdi
testq %rdi, %rdi
je 0xc9ab
movq 0x50(%rsp,%rbx), %rsi
subq %rdi, %rsi
callq 0x2260
movb $0x0, 0x38(%rsp,%rbx)
addq $-0x28, %rbx
cmpq $-0x28, %rbx
jne 0xc98d
movl %r14d, %eax
addq $0x628, %rsp            # imm = 0x628
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xca01
jmp 0xca01
jmp 0xca01
jmp 0xca01
jmp 0xca01
jmp 0xca01
jmp 0xc9e1
jmp 0xc9e1
jmp 0xc9e1
movq %rax, %rbx
movq 0x10(%rsp), %rdi
testq %rdi, %rdi
je 0xca04
movq 0x20(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
jmp 0xca04
jmp 0xca01
jmp 0xca01
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0xd5f0
movq %rbx, %rdi
callq 0x23c0