// File: ksherlock[P]wdc-utils/link.cpp
// Function: build_omf_segments()
void build_omf_segments() {


	std::vector< std::pair<unsigned, uint32_t> > remap;

	remap.resize(sections.size());


	// if data + code can fit in one bank, merge them
	// otherwise, merge all data sections and 1 omf segment
	// per code section.

	// code is next segment...
	unsigned code_segment = 0;
	unsigned data_segment = 0;
	{
		omf_segments.emplace_back();
		auto &seg = omf_segments.back();

		code_segment = data_segment = seg.segnum = omf_segments.size();
		seg.kind = 0x0000; // static code segment.

		auto &s = sections[SECT_CODE];

		remap[s.number] = std::make_pair(code_segment, 0);
		append(seg.data, s.data);
		s.data.clear();
	}
	

	uint32_t total_code_size = 0;
	uint32_t total_data_size = 0;
	for (const auto &s : sections) {
		if (s.flags & SEC_REF_ONLY) continue;
		if (s.flags & SEC_DATA) {
			total_data_size += s.size;
		} else {
			total_code_size += s.size;
		}
	}

	// add in UDATA
	total_data_size += sections[SECT_UDATA].size;

	if (total_data_size + sections[SECT_CODE].size > 0xffff) {

		omf_segments.emplace_back();
		auto &seg = omf_segments.back();
		data_segment = seg.segnum = omf_segments.size();
		seg.kind = 0x0001; // static data segment.
	}


	{
		omf::segment &data_seg = omf_segments[data_segment-1];


		// KDATA, DATA, UDATA, other segment order.
		for (auto &s : sections) {
			if (s.flags & SEC_REF_ONLY) continue;
			if ((s.flags & SEC_DATA) == 0) continue;

			remap[s.number] = std::make_pair(data_segment, data_seg.data.size());

			append(data_seg.data, s.data);
			s.data.clear();
		}

		// add in UDATA
		{
			auto &s = sections[SECT_UDATA];
			remap[s.number] = std::make_pair(data_segment, data_seg.data.size());
			append(data_seg.data, s.size, (uint8_t)0);
		}
		// data_seg no longer valid since emplace_back() may invalidate.
	}

	// for all other sections, create a new segment.
	for (auto &s : sections) {
		if (s.flags & SEC_REF_ONLY) continue;
		if (s.flags & SEC_DATA) continue;
		if (s.number == SECT_CODE) continue;


		omf_segments.emplace_back();
		auto &seg = omf_segments.back();

		seg.segnum = omf_segments.size();
		seg.kind = 0x0000; // static code.
		seg.data = std::move(s.data);
		seg.segname = s.name;
		s.data.clear();

		remap[s.number] = std::make_pair(seg.segnum, 0);
	}


	// add a stack segment at the end
	if (flags.S) {
		auto &s = sections[SECT_PAGE0];

		// create stack/dp segment.
		uint32_t size = s.size;
		if (size) {
			// ????
			size = (size + 255) & ~255;


			omf_segments.emplace_back();
			auto &seg = omf_segments.back();

			seg.segnum = omf_segments.size();
			seg.kind = 0x12; // static dp/stack segment.
			seg.data.resize(size, 0);
			seg.loadname = "~Stack";
			omf_segments.emplace_back(std::move(seg));

			// remap SECT_PAGE0...
			remap[s.number] = std::make_pair(seg.segnum, 0);

		} else {
			warnx("page0 is 0 sized. Stack/dp segment not created.");
		}
	}

	// now adjust all the expressions, simplify, and convert to reloc records.
	for (auto &s :sections) {

		auto &x = remap[s.number];

		for (auto &e : s.expressions) {

			e.offset += x.second;

			for (auto &t : e.stack) {
				if (t.tag == OP_LOC) {
					const auto &x = remap[t.section];
					t.section = x.first;
					t.value += x.second;
				}
			}
			simplify_expression(e);

			unsigned segnum = remap[s.number].first;
			to_omf(e, omf_segments.at(segnum-1));
		}
	}

	// and we're done...

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
leaq -0x18(%rbp), %rdi
movq %rdi, -0x1c8(%rbp)
callq 0xc3b0
leaq 0x38e2e(%rip), %rdi     # 0x3f3e0
callq 0xa270
movq -0x1c8(%rbp), %rdi
movq %rax, %rsi
callq 0xc3d0
jmp 0x65c8
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
leaq 0x38feb(%rip), %rdi     # 0x3f5c8
callq 0xc460
jmp 0x65e4
leaq 0x38fdd(%rip), %rdi     # 0x3f5c8
movq %rdi, -0x1d8(%rbp)
callq 0xc4d0
movq -0x1d8(%rbp), %rdi
movq %rax, -0x38(%rbp)
callq 0xc510
movw %ax, %dx
movq -0x38(%rbp), %rcx
movw %dx, (%rcx)
movzwl %ax, %eax
movl %eax, -0x2c(%rbp)
movl %eax, -0x28(%rbp)
movq -0x38(%rbp), %rax
movw $0x0, 0x2(%rax)
leaq 0x38db5(%rip), %rdi     # 0x3f3e0
movl $0x1, %esi
callq 0xa1c0
movq %rax, -0x40(%rbp)
movl $0x0, -0x4c(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x4c(%rbp), %rsi
callq 0xc540
movq %rax, -0x1d0(%rbp)
jmp 0x6656
movq -0x1d0(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, %rdi
leaq -0x48(%rbp), %rsi
callq 0xc590
jmp 0x6681
movq -0x38(%rbp), %rdi
addq $0x50, %rdi
movq -0x40(%rbp), %rsi
addq $0x30, %rsi
callq 0xc5c0
jmp 0x6698
movq -0x40(%rbp), %rdi
addq $0x30, %rdi
callq 0xc650
movl $0x0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
leaq 0x38d26(%rip), %rax     # 0x3f3e0
movq %rax, -0x60(%rbp)
leaq 0x38d1b(%rip), %rdi     # 0x3f3e0
callq 0x9d70
movq %rax, -0x68(%rbp)
leaq 0x38d0b(%rip), %rdi     # 0x3f3e0
callq 0x9da0
movq %rax, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x9dd0
testb $0x1, %al
jne 0x66f1
jmp 0x6768
leaq -0x68(%rbp), %rdi
callq 0x9e10
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x672a
jmp 0x675a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x18(%rbp), %rdi
callq 0xc950
jmp 0x6f8a
movq -0x78(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x674b
movq -0x78(%rbp), %rax
movl 0x28(%rax), %eax
addl -0x54(%rbp), %eax
movl %eax, -0x54(%rbp)
jmp 0x6758
movq -0x78(%rbp), %rax
movl 0x28(%rax), %eax
addl -0x50(%rbp), %eax
movl %eax, -0x50(%rbp)
jmp 0x675a
leaq -0x68(%rbp), %rdi
callq 0xa070
jmp 0x66de
leaq 0x38c71(%rip), %rdi     # 0x3f3e0
movl $0x4, %esi
callq 0xa1c0
movl 0x28(%rax), %eax
addl -0x54(%rbp), %eax
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
movl %eax, -0x1dc(%rbp)
leaq 0x38c4e(%rip), %rdi     # 0x3f3e0
movl $0x1, %esi
callq 0xa1c0
movq %rax, %rcx
movl -0x1dc(%rbp), %eax
addl 0x28(%rcx), %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jbe 0x67f0
leaq 0x38e12(%rip), %rdi     # 0x3f5c8
callq 0xc460
jmp 0x67bd
leaq 0x38e04(%rip), %rdi     # 0x3f5c8
callq 0xc4d0
movq %rax, -0x80(%rbp)
leaq 0x38df4(%rip), %rdi     # 0x3f5c8
callq 0xc510
movq -0x80(%rbp), %rcx
movw %ax, (%rcx)
movzwl %ax, %eax
movl %eax, -0x2c(%rbp)
movq -0x80(%rbp), %rax
movw $0x1, 0x2(%rax)
movl -0x2c(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq 0x38dc7(%rip), %rdi     # 0x3f5c8
callq 0xc670
movq %rax, -0x88(%rbp)
leaq 0x38bcc(%rip), %rax     # 0x3f3e0
movq %rax, -0x90(%rbp)
leaq 0x38bbe(%rip), %rdi     # 0x3f3e0
callq 0x9d70
movq %rax, -0x98(%rbp)
leaq 0x38bab(%rip), %rdi     # 0x3f3e0
callq 0x9da0
movq %rax, -0xa0(%rbp)
leaq -0x98(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x9dd0
testb $0x1, %al
jne 0x685d
jmp 0x6956
leaq -0x98(%rbp), %rdi
callq 0x9e10
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x6888
jmp 0x6945
movq -0xa8(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
jne 0x68a2
jmp 0x6945
movq -0x88(%rbp), %rdi
addq $0x50, %rdi
callq 0xa700
movq %rax, -0xc0(%rbp)
leaq -0x2c(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0xc690
movq %rdx, -0x1e8(%rbp)
movl %eax, -0x1e0(%rbp)
jmp 0x68d8
movq -0x1e8(%rbp), %rax
movl -0x1e0(%rbp), %ecx
movl %ecx, -0xb8(%rbp)
movq %rax, -0xb0(%rbp)
movq -0xa8(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, %rdi
leaq -0xb8(%rbp), %rsi
callq 0xc6c0
jmp 0x6918
movq -0x88(%rbp), %rdi
addq $0x50, %rdi
movq -0xa8(%rbp), %rsi
addq $0x30, %rsi
callq 0xc5c0
jmp 0x6935
movq -0xa8(%rbp), %rdi
addq $0x30, %rdi
callq 0xc650
leaq -0x98(%rbp), %rdi
callq 0xa070
jmp 0x6841
leaq 0x38a83(%rip), %rdi     # 0x3f3e0
movl $0x4, %esi
callq 0xa1c0
movq %rax, -0xc8(%rbp)
movq -0x88(%rbp), %rdi
addq $0x50, %rdi
callq 0xa700
movq %rax, -0xe0(%rbp)
leaq -0x2c(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0xc690
movq %rdx, -0x1f8(%rbp)
movl %eax, -0x1ec(%rbp)
jmp 0x69a4
movq -0x1f8(%rbp), %rax
movl -0x1ec(%rbp), %ecx
movl %ecx, -0xd8(%rbp)
movq %rax, -0xd0(%rbp)
movq -0xc8(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, %rdi
leaq -0xd8(%rbp), %rsi
callq 0xc6c0
jmp 0x69e4
movq -0x88(%rbp), %rdi
addq $0x50, %rdi
movq -0xc8(%rbp), %rax
movl 0x28(%rax), %esi
movb $0x0, -0xe1(%rbp)
leaq -0xe1(%rbp), %rdx
callq 0xc6f0
jmp 0x6a0e
leaq 0x389cb(%rip), %rax     # 0x3f3e0
movq %rax, -0xf0(%rbp)
leaq 0x389bd(%rip), %rdi     # 0x3f3e0
callq 0x9d70
movq %rax, -0xf8(%rbp)
leaq 0x389aa(%rip), %rdi     # 0x3f3e0
callq 0x9da0
movq %rax, -0x100(%rbp)
leaq -0xf8(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x9dd0
testb $0x1, %al
jne 0x6a5e
jmp 0x6bb4
leaq -0xf8(%rbp), %rdi
callq 0x9e10
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x6a89
jmp 0x6ba3
movq -0x108(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x6aa3
jmp 0x6ba3
movq -0x108(%rbp), %rax
cmpl $0x1, 0x2c(%rax)
jne 0x6ab5
jmp 0x6ba3
leaq 0x38b0c(%rip), %rdi     # 0x3f5c8
callq 0xc460
jmp 0x6ac3
leaq 0x38afe(%rip), %rdi     # 0x3f5c8
movq %rdi, -0x200(%rbp)
callq 0xc4d0
movq -0x200(%rbp), %rdi
movq %rax, -0x110(%rbp)
callq 0xc510
movw %ax, %cx
movq -0x110(%rbp), %rax
movw %cx, (%rax)
movq -0x110(%rbp), %rax
movw $0x0, 0x2(%rax)
movq -0x108(%rbp), %rsi
addq $0x30, %rsi
movq -0x110(%rbp), %rdi
addq $0x50, %rdi
callq 0xc750
movq -0x108(%rbp), %rsi
movq -0x110(%rbp), %rdi
addq $0x30, %rdi
callq 0x3040
jmp 0x6b37
movq -0x108(%rbp), %rdi
addq $0x30, %rdi
callq 0xc650
movq -0x110(%rbp), %rdi
movl $0x0, -0x11c(%rbp)
leaq -0x11c(%rbp), %rsi
callq 0xc780
movq %rax, -0x208(%rbp)
jmp 0x6b6d
movq -0x208(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x108(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, %rdi
leaq -0x118(%rbp), %rsi
callq 0xc7b0
jmp 0x6ba1
jmp 0x6ba3
leaq -0xf8(%rbp), %rdi
callq 0xa070
jmp 0x6a42
testb $0x1, 0x38786(%rip)     # 0x3f341
je 0x6d1f
leaq 0x38818(%rip), %rdi     # 0x3f3e0
xorl %eax, %eax
movl %eax, %esi
callq 0xa1c0
movq %rax, -0x128(%rbp)
movq -0x128(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0x12c(%rbp)
cmpl $0x0, -0x12c(%rbp)
je 0x6d0b
movl -0x12c(%rbp), %eax
addl $0xff, %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
movl %eax, -0x12c(%rbp)
leaq 0x389b6(%rip), %rdi     # 0x3f5c8
callq 0xc460
jmp 0x6c19
leaq 0x389a8(%rip), %rdi     # 0x3f5c8
movq %rdi, -0x210(%rbp)
callq 0xc4d0
movq -0x210(%rbp), %rdi
movq %rax, -0x138(%rbp)
callq 0xc510
movw %ax, %cx
movq -0x138(%rbp), %rax
movw %cx, (%rax)
movq -0x138(%rbp), %rax
movw $0x12, 0x2(%rax)
movq -0x138(%rbp), %rdi
addq $0x50, %rdi
movl -0x12c(%rbp), %eax
movl %eax, %esi
movb $0x0, -0x139(%rbp)
leaq -0x139(%rbp), %rdx
callq 0xc7e0
jmp 0x6c81
movq -0x138(%rbp), %rdi
addq $0x10, %rdi
leaq 0x248e5(%rip), %rsi     # 0x2b578
callq 0x3440
jmp 0x6c9a
movq -0x138(%rbp), %rsi
leaq 0x38920(%rip), %rdi     # 0x3f5c8
callq 0xc890
jmp 0x6caf
movq -0x138(%rbp), %rdi
movl $0x0, -0x148(%rbp)
leaq -0x148(%rbp), %rsi
callq 0xc780
movq %rax, -0x218(%rbp)
jmp 0x6cd5
movq -0x218(%rbp), %rax
movq %rax, -0x144(%rbp)
movq -0x128(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, %rdi
leaq -0x144(%rbp), %rsi
callq 0xc7b0
jmp 0x6d09
jmp 0x6d1d
leaq 0x2486d(%rip), %rdi     # 0x2b57f
xorl %eax, %eax
callq 0x3360
jmp 0x6d1b
jmp 0x6d1d
jmp 0x6d1f
leaq 0x386ba(%rip), %rax     # 0x3f3e0
movq %rax, -0x150(%rbp)
leaq 0x386ac(%rip), %rdi     # 0x3f3e0
callq 0x9d70
movq %rax, -0x158(%rbp)
leaq 0x38699(%rip), %rdi     # 0x3f3e0
callq 0x9da0
movq %rax, -0x160(%rbp)
leaq -0x158(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x9dd0
testb $0x1, %al
jne 0x6d6f
jmp 0x6f78
leaq -0x158(%rbp), %rdi
callq 0x9e10
movq %rax, -0x168(%rbp)
movq -0x168(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, -0x170(%rbp)
movq -0x168(%rbp), %rax
addq $0x48, %rax
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rdi
callq 0x9e30
movq %rax, -0x180(%rbp)
movq -0x178(%rbp), %rdi
callq 0x9e60
movq %rax, -0x188(%rbp)
leaq -0x180(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x9e90
testb $0x1, %al
jne 0x6df2
jmp 0x6f65
leaq -0x180(%rbp), %rdi
callq 0x9ed0
movq %rax, -0x190(%rbp)
movq -0x170(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x190(%rbp), %rax
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
movq -0x190(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x198(%rbp)
movq -0x198(%rbp), %rdi
callq 0x9ef0
movq %rax, -0x1a0(%rbp)
movq -0x198(%rbp), %rdi
callq 0x9f20
movq %rax, -0x1a8(%rbp)
leaq -0x1a0(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x9f50
testb $0x1, %al
jne 0x6e6d
jmp 0x6ee5
leaq -0x1a0(%rbp), %rdi
callq 0x9f90
movq %rax, -0x1b0(%rbp)
movq -0x1b0(%rbp), %rax
cmpl $0x3, (%rax)
jne 0x6ed2
movq -0x1b0(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movq %rax, -0x1b8(%rbp)
movq -0x1b8(%rbp), %rax
movl (%rax), %ecx
movq -0x1b0(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x1b8(%rbp), %rax
movl 0x4(%rax), %ecx
movq -0x1b0(%rbp), %rax
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
jmp 0x6ed4
leaq -0x1a0(%rbp), %rdi
callq 0xa000
jmp 0x6e54
movq -0x190(%rbp), %rdi
callq 0x22140
jmp 0x6ef3
movq -0x168(%rbp), %rax
movl 0x2c(%rax), %eax
movl %eax, %esi
leaq -0x18(%rbp), %rdi
callq 0xc570
movl (%rax), %eax
movl %eax, -0x1bc(%rbp)
movq -0x190(%rbp), %rax
movq %rax, -0x228(%rbp)
movl -0x1bc(%rbp), %eax
decl %eax
movl %eax, %esi
leaq 0x38699(%rip), %rdi     # 0x3f5c8
callq 0xc910
movq %rax, -0x220(%rbp)
jmp 0x6f3d
movq -0x220(%rbp), %rsi
movq -0x228(%rbp), %rdi
callq 0x6090
jmp 0x6f52
jmp 0x6f54
leaq -0x180(%rbp), %rdi
callq 0xa050
jmp 0x6dd6
jmp 0x6f67
leaq -0x158(%rbp), %rdi
callq 0xa070
jmp 0x6d53
leaq -0x18(%rbp), %rdi
callq 0xc950
addq $0x230, %rsp            # imm = 0x230
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x3540
nopw %cs:(%rax,%rax)