// File: /workspace/github_c_makefile_star2_O3/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, %ebx
movl %r8d, 0x10(%rsp)
movl %ecx, 0x20(%rsp)
movq %rdx, %rbp
movq %rsi, %r12
movq %rdi, %r13
movslq 0x1d8(%rdi), %rdi
shlq $0x3, %rdi
callq 0x6638
movq %rax, %r14
movslq 0x1d8(%r13), %rdi
shlq $0x2, %rdi
callq 0x6686
movq $-0x1, %rdx
movl %ebx, 0x24(%rsp)
movl %ebx, %ecx
shlq %cl, %rdx
movq %rdx, 0x18(%rsp)
movq %rax, %r15
cmpl $0x0, 0x1d8(%r13)
jle 0x1368b
xorl %ebx, %ebx
movl $0x18, %edi
callq 0x6638
movq %rax, (%r14,%rbx,8)
movq %rax, %rdi
callq 0x66da
incq %rbx
movslq 0x1d8(%r13), %rax
cmpq %rax, %rbx
jl 0x13666
movl 0x24(%rsp), %ebx
cmpw $0x18, %bx
movl 0x10(%rsp), %esi
je 0x136b4
movzwl %bx, %eax
cmpl $0xe, %eax
jne 0x136c7
movl $0x10, %r8d
movl $0xffff, %r9d           # imm = 0xFFFF
movl $0xfffc, %edi           # imm = 0xFFFC
jmp 0x136d5
movl $0x6, %r8d
movl $0x3ffffff, %r9d        # imm = 0x3FFFFFF
movl $0x3fffffc, %edi        # imm = 0x3FFFFFC
jmp 0x136d5
movq 0x18(%rsp), %rdi
notq %rdi
xorl %r8d, %r8d
movq %rdi, %r9
movq (%rbp), %rcx
testq %rcx, %rcx
je 0x13936
movl %r8d, %eax
shrl $0x3, %eax
movq %rax, 0x30(%rsp)
movl $0x1, 0xc(%rsp)
xorl %eax, %eax
movq %r13, (%rsp)
movq %rdi, 0x18(%rsp)
movl %r8d, 0x14(%rsp)
movq %r9, 0x28(%rsp)
movq %rbp, %r13
movq %rcx, %rbp
cmpb %sil, 0x38(%r13)
jne 0x137cf
movq 0x30(%r13), %rcx
testq %rcx, %rcx
je 0x137cf
movzwl 0x8(%rcx), %edx
cmpl %edx, %r8d
jne 0x137cf
cmpw %bx, 0xa(%rcx)
jne 0x137cf
movq 0x10(%rcx), %rcx
andq %r9, %rcx
cmpq %rdi, %rcx
jne 0x137cf
movq %r13, %rdi
callq 0x6759
movq 0x18(%r13), %rax
movslq 0x10(%rax), %rax
movq (%r14,%rax,8), %rdi
movq %r13, %rsi
callq 0x6729
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 0x30(%rsp), %rdx
movq %rdx, 0x20(%r13)
movl $0x1, %eax
movq (%rsp), %r13
cmpb $0x4, 0x6e(%r13)
jne 0x137ba
cmpl $0xffff, %ecx           # imm = 0xFFFF
movl 0xc(%rsp), %ecx
movl $0x0, %esi
cmovgel %esi, %ecx
cmpq $0x10000, %rdx          # imm = 0x10000
cmovael %esi, %ecx
movl %ecx, 0xc(%rsp)
movl 0x10(%rsp), %esi
movq 0x18(%rsp), %rdi
movl 0x14(%rsp), %r8d
movq 0x28(%rsp), %r9
jmp 0x137d3
movq (%rsp), %r13
movq (%rbp), %rcx
testq %rcx, %rcx
jne 0x1370a
testl %eax, %eax
je 0x13936
movl 0x20(%rsp), %esi
cmpl $0x3ec, %esi            # imm = 0x3EC
jne 0x138ad
cmpb $0x4, 0x6e(%r13)
jne 0x138ad
cmpl $0x0, 0xc(%rsp)
je 0x138ad
xorl %eax, %eax
cmpl $0x0, 0x54(%r13)
setne %al
leal (%rax,%rax,4), %esi
addl $0x3f7, %esi            # imm = 0x3F7
movq %r12, %rdi
callq 0x6be8
cmpl $0x0, 0x1d8(%r13)
jle 0x1389e
xorl %r13d, %r13d
movl $0xffff, %ebx           # imm = 0xFFFF
xorl %ebp, %ebp
movl (%r15,%r13,4), %esi
testl %esi, %esi
je 0x1387d
andl %ebx, %esi
movq %r12, %rdi
callq 0x6c3a
movl %r13d, %esi
andl %ebx, %esi
movq %r12, %rdi
callq 0x6c3a
addl $0x2, %ebp
movq (%r14,%r13,8), %rdi
callq 0x673f
testq %rax, %rax
je 0x1387d
movzwl 0x20(%rax), %esi
movq %r12, %rdi
callq 0x6c3a
incl %ebp
jmp 0x1385f
incq %r13
movq (%rsp), %rax
movslq 0x1d8(%rax), %rax
cmpq %rax, %r13
jl 0x1383d
testb $0x1, %bpl
movq (%rsp), %r13
jne 0x13970
movq %r12, %rdi
xorl %esi, %esi
callq 0x6be8
jmp 0x13936
movq %r12, %rdi
callq 0x6be8
movl 0x1d8(%r13), %eax
testl %eax, %eax
jle 0x13928
xorl %r13d, %r13d
movl $0x10000, %ebx          # imm = 0x10000
movl (%r15,%r13,4), %ebp
testl %ebp, %ebp
je 0x1391d
cmpl %ebx, %ebp
cmovgel %ebx, %ebp
movq %r12, %rdi
movl %ebp, %esi
callq 0x6be8
movq %r12, %rdi
movl %r13d, %esi
callq 0x6be8
subl %ebp, (%r15,%r13,4)
movq (%r14,%r13,8), %rdi
callq 0x673f
testq %rax, %rax
je 0x13907
movl 0x20(%rax), %esi
movq %r12, %rdi
callq 0x6be8
decl %ebp
jne 0x138ee
movl (%r15,%r13,4), %ebp
testl %ebp, %ebp
jne 0x138d0
movq (%rsp), %rax
movl 0x1d8(%rax), %eax
incq %r13
movslq %eax, %rcx
cmpq %rcx, %r13
jl 0x138c8
movq %r12, %rdi
xorl %esi, %esi
callq 0x6be8
movq (%rsp), %r13
cmpl $0x0, 0x1d8(%r13)
jle 0x1395a
xorl %ebx, %ebx
movq (%r14,%rbx,8), %rdi
incq %rbx
callq 0x5040
movslq 0x1d8(%r13), %rax
cmpq %rax, %rbx
jl 0x13942
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 0x6c3a
jmp 0x13936