// File: /workspace/github_c_makefile_star2_O2/deplinenoise[P]vlink/t_amigahunk.c
// Function: reloc_hunk
static void reloc_hunk(struct GlobalVars *gv,FILE *f,
                       struct LinkedSection *sec,uint32_t relhunk,
                       uint8_t rtype,uint16_t rsize)
/* generate an AmigaDOS/EHF relocation hunk for a specific reloc type */
{
  struct Reloc *nextrel,*rel=(struct Reloc *)sec->relocs.first;
  struct list **rlist=alloc(gv->nsecs*sizeof(struct list *));
  int *rcnt=alloczero(gv->nsecs*sizeof(int)); /* reloc cnt for all sect. */
  bool hunk_required=FALSE,small_offsets=TRUE;
  lword chkmask,rmask=makemask(rsize);
  uint16_t rpos=0;
  int i;

  for (i=0; i<gv->nsecs; i++) {  /* empty reloc lists for each section */
    rlist[i] = alloc(sizeof(struct list));
    initlist(rlist[i]);
  }

  /* EHF-PowerPC relocations need special treatment */
  if (rsize == 24) {
    rpos = 6;
    rmask = 0x3ffffff;
    chkmask = 0x3fffffc;
  }
  else if (rsize == 14) {
    rpos = 16;
    rmask = 0xffff;
    chkmask = 0xfffc;
  }
  else
    chkmask = rmask;

  while (nextrel = (struct Reloc *)rel->n.next) {
    struct RelocInsert *ri;
    int newrcnt;

    if (rel->rtype==rtype && (ri=rel->insert)!=NULL) {
      if (ri->bpos==rpos && ri->bsiz==rsize && (ri->mask&rmask)==chkmask) {
        /* move reloc node of correct type into relocssect's rlist */
        remnode(&rel->n);
        addtail(rlist[rel->relocsect.lnk->index],&rel->n);
        newrcnt = ++rcnt[rel->relocsect.lnk->index];
        rel->offset += rpos >> 3;
        if (gv->reloctab_format == RTAB_SHORTOFF) {
          if (rel->offset>=0x10000 || newrcnt>=0x10000)
            small_offsets = FALSE; /* no short-reloc hunk would be possible */
        }
        hunk_required = TRUE;
      }
    }
    rel = nextrel;
  }

  if (hunk_required) {  /* there's at least one relocation */

    if (relhunk==HUNK_ABSRELOC32 &&
        gv->reloctab_format==RTAB_SHORTOFF && small_offsets) {
      /* Make a short hunk with 16-bit offsets.
         For executables, HUNK_DREL32 is used instead of the correct
         HUNK_RELOC32SHORT to be compatible with OS2.0 */
      int cnt=0;

      if (gv->dest_object)
        fwrite32be(f,HUNK_RELOC32SHORT);
      else
        fwrite32be(f,HUNK_DREL32);
      for (i=0; i<gv->nsecs; i++) {
        if (rcnt[i]) {
          fwrite16be(f,(uint16_t)rcnt[i]);  /* number of relocations */
          fwrite16be(f,(uint16_t)i);  /* section index */
          cnt += 2;

          /* store relocation offsets */
          while(rel = (struct Reloc *)remhead(rlist[i])) {
            fwrite16be(f,(uint16_t)rel->offset);
            cnt++;
          }
        }
      }
      /* no more relocation entries */
      if (cnt & 1)  /* 0-word for 32-bit alignment */
        fwrite16be(f,0);
      else
        fwrite32be(f,0);
    }

    else {
      /* all other relocation hunks */
      fwrite32be(f,relhunk);  /* reloc hunk id */
      for (i=0; i<gv->nsecs; i++) {
        while (rcnt[i]) {
          /* never write more than 65536 relocs at once - there is a bug */
          /* in dos.library which rejects the executable file otherwise */
          int n = (rcnt[i]>0x10000) ? 0x10000 : rcnt[i];

          fwrite32be(f,(uint32_t)n);  /* number of relocations */
          fwrite32be(f,(uint32_t)i);  /* section index */
          rcnt[i] -= n;

          /* store relocation offsets */
          while (n--) {
            if (rel = (struct Reloc *)remhead(rlist[i])) {
              fwrite32be(f,(uint32_t)rel->offset);
            }
          }
        }
      }
      fwrite32be(f,0);  /* no more relocation entries */
    }
  }

  /* free dynamically allocated rlists and rcnt array */
  for (i=0; i<gv->nsecs; free(rlist[i++]));
  free(rcnt);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %r9d, %r15d
movl %r8d, 0xc(%rsp)
movl %ecx, 0x20(%rsp)
movq %rsi, %r12
movq %rdi, %rbx
movq 0x80(%rdx), %rbp
movslq 0x1d8(%rdi), %rdi
shlq $0x3, %rdi
callq 0x6340
movq %rax, %r14
movq %rbx, (%rsp)
movslq 0x1d8(%rbx), %rdi
shlq $0x2, %rdi
callq 0x638a
pushq $-0x1
popq %rdx
movl %r15d, 0x24(%rsp)
movl %r15d, %ecx
shlq %cl, %rdx
movq %rdx, 0x10(%rsp)
movq %rax, %r15
xorl %ebx, %ebx
pushq $0x18
popq %r13
movq (%rsp), %rax
movslq 0x1d8(%rax), %rax
cmpq %rax, %rbx
jge 0x12666
movq %r13, %rdi
callq 0x6340
movq %rax, (%r14,%rbx,8)
movq %rax, %rdi
callq 0x63c8
incq %rbx
jmp 0x1263d
movl 0x24(%rsp), %ebx
cmpw $0x18, %bx
je 0x12691
movzwl %bx, %eax
cmpl $0xe, %eax
movl 0xc(%rsp), %edi
jne 0x126aa
pushq $0x10
popq %rsi
movl $0xffff, %r8d           # imm = 0xFFFF
movl $0xfffc, %eax           # imm = 0xFFFC
movq %rax, 0x10(%rsp)
jmp 0x126bc
pushq $0x6
popq %rsi
movl $0x3ffffff, %r8d        # imm = 0x3FFFFFF
movl $0x3fffffc, %eax        # imm = 0x3FFFFFC
movq %rax, 0x10(%rsp)
movl 0xc(%rsp), %edi
jmp 0x126bc
movq 0x10(%rsp), %rax
notq %rax
xorl %esi, %esi
movq %rax, 0x10(%rsp)
movq %rax, %r8
movl %esi, %r10d
shrl $0x3, %r10d
movb $0x1, %al
pushq $0x1
popq %r9
movq %rbp, %r13
movq (%rbp), %rbp
testq %rbp, %rbp
je 0x12792
cmpb %dil, 0x38(%r13)
jne 0x126c9
movq 0x30(%r13), %rcx
testq %rcx, %rcx
je 0x126c9
movzwl 0x8(%rcx), %edx
cmpl %edx, %esi
jne 0x126c9
cmpw %bx, 0xa(%rcx)
jne 0x126c9
movq 0x10(%rcx), %rcx
andq %r8, %rcx
cmpq 0x10(%rsp), %rcx
jne 0x126c9
movq %r13, %rdi
movl %esi, 0x1c(%rsp)
movq %r8, 0x30(%rsp)
movl %r9d, 0x18(%rsp)
movq %r10, 0x28(%rsp)
callq 0x6444
movq 0x18(%r13), %rax
movslq 0x10(%rax), %rax
movq (%r14,%rax,8), %rdi
movq %r13, %rsi
callq 0x6414
movq 0x28(%rsp), %r10
movl 0x18(%rsp), %r9d
movq 0x30(%rsp), %r8
movl 0xc(%rsp), %edi
movq 0x18(%r13), %rax
movslq 0x10(%rax), %rax
movl (%r15,%rax,4), %ecx
leal 0x1(%rcx), %edx
movl %edx, (%r15,%rax,4)
movq 0x20(%r13), %rdx
addq %r10, %rdx
movq %rdx, 0x20(%r13)
xorl %eax, %eax
movq (%rsp), %rsi
cmpb $0x4, 0x6e(%rsi)
movl 0x1c(%rsp), %esi
jne 0x126c9
cmpl $0xffff, %ecx           # imm = 0xFFFF
cmovgel %eax, %r9d
cmpq $0x10000, %rdx          # imm = 0x10000
cmovael %eax, %r9d
jmp 0x126c9
testb $0x1, %al
jne 0x128bd
movl 0x20(%rsp), %esi
cmpl $0x3ec, %esi            # imm = 0x3EC
jne 0x12842
movq (%rsp), %rax
cmpb $0x4, 0x6e(%rax)
jne 0x12842
testl %r9d, %r9d
je 0x12842
xorl %eax, %eax
movq (%rsp), %rcx
cmpl $0x0, 0x54(%rcx)
setne %al
leal (%rax,%rax,4), %esi
addl $0x3f7, %esi            # imm = 0x3F7
movq %r12, %rdi
callq 0x6856
xorl %r13d, %r13d
movl $0xffff, %ebx           # imm = 0xFFFF
xorl %ebp, %ebp
movq (%rsp), %rax
movslq 0x1d8(%rax), %rax
cmpq %rax, %r13
jge 0x128ad
movl (%r15,%r13,4), %esi
testl %esi, %esi
je 0x1283d
andl %ebx, %esi
movq %r12, %rdi
callq 0x68a2
movl %r13d, %esi
andl %ebx, %esi
movq %r12, %rdi
callq 0x68a2
addl $0x2, %ebp
movq (%r14,%r13,8), %rdi
callq 0x642a
testq %rax, %rax
je 0x1283d
movzwl 0x20(%rax), %esi
movq %r12, %rdi
callq 0x68a2
incl %ebp
jmp 0x1281f
incq %r13
jmp 0x127e9
movq %r12, %rdi
callq 0x6856
xorl %r13d, %r13d
movl $0x10000, %ebx          # imm = 0x10000
movq (%rsp), %rax
movslq 0x1d8(%rax), %rax
cmpq %rax, %r13
jge 0x128b3
movl (%r15,%r13,4), %ebp
testl %ebp, %ebp
je 0x128a8
cmpl %ebx, %ebp
cmovgel %ebx, %ebp
movq %r12, %rdi
movl %ebp, %esi
callq 0x6856
movq %r12, %rdi
movl %r13d, %esi
callq 0x6856
subl %ebp, (%r15,%r13,4)
subl $0x1, %ebp
jb 0x12862
movq (%r14,%r13,8), %rdi
callq 0x642a
testq %rax, %rax
je 0x12888
movl 0x20(%rax), %esi
movq %r12, %rdi
callq 0x6856
jmp 0x12888
incq %r13
jmp 0x12852
testb $0x1, %bpl
jne 0x128f3
movq %r12, %rdi
xorl %esi, %esi
callq 0x6856
xorl %ebx, %ebx
movq (%rsp), %rax
movslq 0x1d8(%rax), %rax
cmpq %rax, %rbx
jge 0x128dd
movq (%r14,%rbx,8), %rdi
incq %rbx
callq 0x5040
jmp 0x128bf
movq %r15, %rdi
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x5040
movq %r12, %rdi
xorl %esi, %esi
callq 0x68a2
jmp 0x128bd