// File: /workspace/github_c_makefile_star2_O2/mrkite[P]regs/src/omf.cc
// Function: OMF::relocSegments()
bool OMF::relocSegments() {
  for (auto &seg : segments) {
    auto done = false;
    auto pc = seg.mapped;
    auto data = std::vector<uint8_t>(seg.length);
    handle->seek(seg.offset);
    while (!done) {
      auto opcode = handle->r8();
      switch (opcode) {
        case DONE:
          done = true;
          break;
        case RELOC:
          {
            auto numBytes = handle->r8();
            auto bitShift = static_cast<int8_t>(handle->r8());
            auto offset = handle->r32();
            auto subOffset = handle->r32() + seg.mapped;
            if (bitShift < 0) {
              subOffset >>= -bitShift;
            } else {
              subOffset <<= bitShift;
            }
            patch(data, offset, numBytes, subOffset);
          }
          break;
        case INTERSEG:
          {
            auto numBytes = handle->r8();
            auto bitShift = static_cast<int8_t>(handle->r8());
            auto offset = handle->r32();
            handle->skip(2);  // filenum
            auto segnum = handle->r16();
            auto subOffset = handle->r32();
            for (auto &sub : segments) {
              if (sub.segnum == segnum) {
                subOffset += sub.mapped;
                break;
              }
            }
            if (bitShift < 0) {
              subOffset >>= -bitShift;
            } else {
              subOffset <<= bitShift;
            }
            patch(data, offset, numBytes, subOffset);
          }
          break;
        case DS:
          pc += handle->r32();  // filled with zeros
          break;
        case LCONST:
          {
            auto count = handle->r32();
            auto v = handle->readBytes(count);
            std::copy(v.begin(), v.end(), data.begin() + (pc - seg.mapped));
            pc += count;
          }
          break;
        case cRELOC:
          {
            auto numBytes = handle->r8();
            auto bitShift = static_cast<int8_t>(handle->r8());
            auto offset = handle->r16();
            auto subOffset = handle->r16() + seg.mapped;
            if (bitShift < 0) {
              subOffset >>= -bitShift;
            } else {
              subOffset <<= bitShift;
            }
            patch(data, offset, numBytes, subOffset);
          }
          break;
        case cINTERSEG:
          {
            auto numBytes = handle->r8();
            auto bitShift = static_cast<int8_t>(handle->r8());
            auto offset = handle->r16();
            auto segnum = handle->r8();
            int32_t subOffset = handle->r16();
            for (auto &sub : segments) {
              if (sub.segnum == segnum) {
                subOffset += sub.mapped;
                break;
              }
            }
            if (bitShift < 0) {
              subOffset >>= -bitShift;
            } else {
              subOffset <<= bitShift;
            }
            patch(data, offset, numBytes, subOffset);
          }
          break;
        case SUPER:
          {
            auto superLen = handle->r32();
            superLen += handle->tell();
            auto superType = handle->r8();
            int32_t superPage = 0;
            while (handle->tell() < superLen) {
              auto numOfs = handle->r8();
              if (numOfs & 0x80) {
                superPage += 256 * (numOfs & 0x7f);
                continue;
              }
              auto subHandle = TheHandle::createFromArray(data);
              for (auto o = 0; o <= numOfs; o++) {
                auto offset = superPage | handle->r8();
                uint8_t numBytes = 0;
                subHandle->seek(offset);
                int32_t subOffset = subHandle->r16();
                if (superType == 0 || superType == 1) {
                  subOffset += seg.mapped;
                  numBytes = superType + 2;
                } else if (superType < 14) {  // INTERSEG1-12
                  auto segnum = subHandle->r8();
                  for (auto &sub : segments) {
                    if (sub.segnum == segnum) {
                      subOffset += sub.mapped;
                      break;
                    }
                  }
                  numBytes = 3;
                } else if (superType < 26) {  // INTERSEG13-14
                  auto segnum = superType - 13;
                  for (auto &sub : segments) {
                    if (sub.segnum == segnum) {
                      subOffset += sub.mapped;
                      break;
                    }
                  }
                  numBytes = 2;
                } else {  // INTERSEG25-36
                  auto segnum = superType - 25;
                  for (auto &sub : segments) {
                    if (sub.segnum == segnum) {
                      subOffset += sub.mapped;
                      break;
                    }
                  }
                  subOffset >>= 16;
                  numBytes = 2;
                }
                patch(data, offset, numBytes, subOffset);
              }
              superPage += 256;
            }
          }
          break;
        default:
          if (opcode < 0xe0) {
            auto v = handle->readBytes(opcode);
            std::copy(v.begin(), v.end(), data.begin() + (pc - seg.mapped));
            pc += opcode;
          } else {
            fprintf(stderr, "Unknown segment opcode: $%02x\n", opcode);
            return false;
          }
          break;
      }
    }
    if (seg.isJump()) {  // patch jumptable
      for (int i = 8; i < seg.length - 14; i += 14) {
        uint16_t segnum = data[i + 4] | (data[i + 5] << 8);
        int32_t subOffset = data[i + 6] | (data[i + 7] << 8) |
            (data[i + 8] << 16) | (data[i + 9] << 24);
        for (auto &sub : segments) {
          if (sub.segnum == segnum) {
            subOffset += sub.mapped;
            break;
          }
        }
        patch(data, i + 11, 3, subOffset);
      }
    }
    seg.data = TheHandle::createFromArray(data);
  }
  return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, %r14
movq 0x10(%rdi), %rax
movq 0x18(%rdi), %rcx
movq %rcx, 0x58(%rsp)
leaq 0x30(%rsp), %r15
leaq 0xd45a(%rip), %r12      # 0x14220
movq %rax, %rbx
cmpq 0x58(%rsp), %rax
je 0x735d
movl 0x60(%rbx), %eax
movl %eax, 0x4(%rsp)
movslq 0x8(%rbx), %rsi
leaq 0x18(%rsp), %rdi
movq %r15, %rdx
callq 0x75f8
movq (%r14), %rdi
movq %rbx, 0x8(%rsp)
movq 0x48(%rbx), %rsi
callq 0x8a68
xorl %eax, %eax
movl %eax, %ebp
testb $0x1, %al
jne 0x7286
movq (%r14), %rdi
callq 0x8966
movzbl %al, %r13d
leal -0xf1(%r13), %eax
movslq 0x4(%rsp), %rbx
cmpl $0x6, %eax
ja 0x6e8f
movslq (%r12,%rax,4), %rax
addq %r12, %rax
jmpq *%rax
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebx
movq %r15, %r12
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebp
movq (%r14), %rdi
callq 0x8944
movl %eax, %r15d
movq (%r14), %rdi
callq 0x8966
movl %eax, %r13d
movq (%r14), %rdi
callq 0x8944
movzwl %ax, %r8d
movq 0x10(%r14), %rax
movq 0x18(%r14), %rcx
movzbl %r13b, %edx
cmpq %rcx, %rax
je 0x70cc
movswl 0x1c(%rax), %esi
cmpl %edx, %esi
je 0x70c8
addq $0x68, %rax
jmp 0x6e74
movb $0x1, %al
testl %r13d, %r13d
je 0x6dff
cmpl $0xe2, %r13d
je 0x722d
cmpl $0xe3, %r13d
jne 0x7128
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebx
movq %r15, %r12
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebp
movq (%r14), %rdi
callq 0x88ce
movl %eax, %r15d
movq (%r14), %rdi
pushq $0x2
popq %rsi
callq 0x8a72
movq (%r14), %rdi
callq 0x8944
movl %eax, %r13d
movq (%r14), %rdi
callq 0x88ce
movq 0x10(%r14), %rcx
movq 0x18(%r14), %rdx
movzwl %r13w, %esi
cmpq %rdx, %rcx
je 0x70f2
movswl 0x1c(%rcx), %edi
cmpl %esi, %edi
je 0x70ef
addq $0x68, %rcx
jmp 0x6f00
movq (%r14), %rdi
callq 0x88ce
movq %rax, 0x48(%rsp)
movq (%r14), %rdi
callq 0x88c4
movq %rax, %rbx
movq (%r14), %rdi
callq 0x8966
movl %eax, %ecx
movq 0x48(%rsp), %rax
addl %ebx, %eax
movq %rax, 0x48(%rsp)
movb %cl, 0x3(%rsp)
movzbl %cl, %eax
leal -0x19(%rax), %ecx
movl %ecx, 0x54(%rsp)
leal -0xd(%rax), %r12d
orb $0x2, %al
movq %rax, 0x60(%rsp)
movl $0x0, 0x14(%rsp)
movq (%r14), %rdi
callq 0x88c4
cmpq 0x48(%rsp), %rax
jge 0x70b5
movq (%r14), %rdi
callq 0x8966
movzbl %al, %r15d
testb %r15b, %r15b
js 0x70a3
leaq 0x30(%rsp), %rdi
leaq 0x18(%rsp), %rsi
callq 0x8768
movq %r14, %rbp
incl %r15d
xorl %r14d, %r14d
cmpl %r15d, %r14d
je 0x708e
movq (%rbp), %rdi
callq 0x8966
movzbl %al, %ebx
orl 0x14(%rsp), %ebx
movq 0x30(%rsp), %rdi
movq %rbx, %rsi
callq 0x8a68
movq 0x30(%rsp), %rdi
callq 0x8944
movzwl %ax, %r13d
movb 0x3(%rsp), %sil
cmpb $0x1, %sil
ja 0x6ff9
movq 0x8(%rsp), %rax
addl 0x60(%rax), %r13d
movq 0x60(%rsp), %rax
jmp 0x7074
cmpb $0xd, %sil
ja 0x7029
movq 0x30(%rsp), %rdi
callq 0x8966
movq 0x10(%rbp), %rcx
movq 0x18(%rbp), %rdx
movzbl %al, %esi
movb $0x3, %al
cmpq %rdx, %rcx
je 0x7074
movswl 0x1c(%rcx), %edi
cmpl %esi, %edi
je 0x704d
addq $0x68, %rcx
jmp 0x7014
movq 0x10(%rbp), %rcx
movq 0x18(%rbp), %rdx
cmpb $0x1a, %sil
jae 0x7053
movb $0x2, %al
cmpq %rdx, %rcx
je 0x7074
movswl 0x1c(%rcx), %esi
cmpl %esi, %r12d
je 0x704d
addq $0x68, %rcx
jmp 0x7037
addl 0x60(%rcx), %r13d
jmp 0x7074
movl 0x54(%rsp), %esi
cmpq %rdx, %rcx
je 0x706e
movswl 0x1c(%rcx), %eax
cmpl %eax, %esi
je 0x706a
addq $0x68, %rcx
jmp 0x7057
addl 0x60(%rcx), %r13d
sarl $0x10, %r13d
movb $0x2, %al
movzbl %al, %ecx
leaq 0x18(%rsp), %rsi
movl %ebx, %edx
movl %r13d, %r8d
callq 0x75a0
incl %r14d
jmp 0x6faa
leaq 0x38(%rsp), %rdi
callq 0x61e4
movl $0x100, %r15d           # imm = 0x100
movq %rbp, %r14
jmp 0x70ab
andl $0x7f, %r15d
shll $0x8, %r15d
addl %r15d, 0x14(%rsp)
jmp 0x6f6a
xorl %eax, %eax
leaq 0x30(%rsp), %r15
leaq 0xd15d(%rip), %r12      # 0x14220
jmp 0x6dff
addl 0x60(%rax), %r8d
movl %ebp, %ecx
negb %cl
movl %r8d, %eax
sarl %cl, %eax
movl %ebp, %ecx
shll %cl, %r8d
testb %bpl, %bpl
cmovsl %eax, %r8d
movzwl %r15w, %edx
movzbl %bl, %ecx
leaq 0x18(%rsp), %rsi
jmp 0x7112
addl 0x60(%rcx), %eax
movl %ebp, %ecx
negb %cl
movl %eax, %edx
shrl %cl, %edx
movl %ebp, %ecx
shll %cl, %eax
testb %bpl, %bpl
cmovsl %edx, %eax
movzbl %bl, %ecx
leaq 0x18(%rsp), %rsi
movl %r15d, %edx
movl %eax, %r8d
callq 0x75a0
xorl %eax, %eax
movq %r12, %r15
leaq 0xd0fd(%rip), %r12      # 0x14220
jmp 0x6dff
cmpb $-0x21, %r13b
ja 0x733b
movq (%r14), %rsi
movq %r15, %rdi
movl %r13d, %edx
callq 0x8a32
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
subq %rsi, %rdx
je 0x7168
movq 0x8(%rsp), %rax
movslq 0x60(%rax), %rax
subq %rax, %rbx
addq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x5390
addl %r13d, 0x4(%rsp)
jmp 0x7220
movq (%r14), %rdi
callq 0x88ce
addl %eax, 0x4(%rsp)
jmp 0x6dfd
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebx
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebp
movq (%r14), %rdi
callq 0x8944
movl %eax, %r13d
movq (%r14), %rdi
callq 0x8944
movzwl %ax, %r8d
movq 0x8(%rsp), %rax
addl 0x60(%rax), %r8d
movl %ebp, %ecx
negb %cl
movl %r8d, %eax
sarl %cl, %eax
movl %ebp, %ecx
shll %cl, %r8d
testb %bpl, %bpl
cmovsl %eax, %r8d
movzwl %r13w, %edx
movzbl %bl, %ecx
leaq 0x18(%rsp), %rsi
jmp 0x727c
movq (%r14), %rdi
callq 0x88ce
movl %eax, %ebp
movq (%r14), %rsi
movq %r15, %rdi
movl %eax, %edx
callq 0x8a32
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
subq %rsi, %rdx
je 0x721c
movq 0x8(%rsp), %rax
movslq 0x60(%rax), %rax
subq %rax, %rbx
addq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x5390
addl %ebp, 0x4(%rsp)
movq %r15, %rdi
callq 0x6662
jmp 0x6dfd
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebx
movq (%r14), %rdi
callq 0x8966
movl %eax, %ebp
movq (%r14), %rdi
callq 0x88ce
movl %eax, %r13d
movq (%r14), %rdi
callq 0x88ce
movq 0x8(%rsp), %rcx
addl 0x60(%rcx), %eax
movl %ebp, %ecx
negb %cl
movl %eax, %edx
shrl %cl, %edx
movl %ebp, %ecx
shll %cl, %eax
testb %bpl, %bpl
cmovsl %edx, %eax
movzbl %bl, %ecx
leaq 0x18(%rsp), %rsi
movl %r13d, %edx
movl %eax, %r8d
callq 0x75a0
jmp 0x6dfd
movq 0x8(%rsp), %rbx
movzwl 0x10(%rbx), %eax
andl $0x1f, %eax
cmpw $0x2, %ax
jne 0x72fe
pushq $0x13
popq %rax
pushq $0x8
popq %rcx
movslq 0x8(%rbx), %rdx
addq $-0xe, %rdx
cmpq %rdx, %rcx
jge 0x72fe
movq 0x18(%rsp), %rdx
movzwl 0x4(%rdx,%rcx), %edi
movl 0x6(%rdx,%rcx), %edx
movq 0x10(%r14), %rsi
movq 0x18(%r14), %r8
cmpq %r8, %rsi
je 0x72d9
movswl 0x1c(%rsi), %r9d
cmpl %r9d, %edi
je 0x72d6
addq $0x68, %rsi
jmp 0x72c1
addl 0x60(%rsi), %edx
xorl %esi, %esi
cmpq $0x3, %rsi
je 0x72f4
movq 0x18(%rsp), %rdi
addq %rax, %rdi
movb %dl, (%rsi,%rdi)
incq %rsi
shrl $0x8, %edx
jmp 0x72db
addq $0xe, %rcx
addq $0xe, %rax
jmp 0x729e
movq %r15, %rdi
leaq 0x18(%rsp), %rsi
callq 0x8768
leaq 0x50(%rbx), %rdi
movq %r15, %rsi
callq 0x76b0
leaq 0x38(%rsp), %rdi
callq 0x61e4
leaq 0x18(%rsp), %rdi
callq 0x6662
leaq 0x68(%rbx), %rax
testb $0x1, %bpl
jne 0x6dc6
jmp 0x735d
movq 0x18c86(%rip), %rax     # 0x1ffc8
movq (%rax), %rdi
leaq 0xcf4e(%rip), %rsi      # 0x1429a
movl %r13d, %edx
xorl %eax, %eax
callq 0x5300
movq 0x8(%rsp), %rbx
jmp 0x7321
cmpq 0x58(%rsp), %rbx
sete %al
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
jmp 0x73ac
movq %rax, %rbx
jmp 0x73c4
jmp 0x73b7
jmp 0x73b7
jmp 0x73b7
movq %rax, %rbx
leaq 0x38(%rsp), %rdi
callq 0x61e4
leaq 0x18(%rsp), %rdi
callq 0x6662
movq %rbx, %rdi
callq 0x53c0