// File: /workspace/github_c_makefile_star2_O0/simh[P]simtools/converters/fsio/os8.c
// Function: os8SplitDirectory
static int os8SplitDirectory(
  struct mountedFS *mount,
  uint8_t unit,
  uint16_t segment
)
{
  struct OS8data *data = &mount->os8data;
  uint16_t inuse = 0;
  uint16_t dirblk = OS8_DSSTART;
  uint16_t buf[OS8_BLOCKSIZE];
  uint16_t empoff[OS8_BLOCKSIZE], emplen[OS8_BLOCKSIZE];
  uint16_t emptotal = 0, emplast = 0, empcount = 0;
  uint16_t i, j, entries, entrysz, extra, startblk, split = 0;
  uint16_t off, target, dst = OS8_DH_SIZE;

  /*
   * First we need to find an unused directory segment.
   */
  do {
    inuse |= (1 << dirblk);

    if (os8ReadBlock(mount, unit, dirblk, buf) == 0)
      return 0;

    dirblk = os8Word(le16toh(buf[OS8_DH_NEXT]));
  } while (dirblk != 0);

  for (i = OS8_DSSTART; i <= OS8_DSLAST; i++) {
    if ((inuse & (1 << i)) == 0) {
      /*
       * Build a new directory segment
       */
      buf[OS8_DH_ENTRIES] = 0;
      buf[OS8_DH_NEXT] = data->buf[OS8_DH_NEXT];
      buf[OS8_DH_FLAGWD] = htole16(os8Value(0));
      buf[OS8_DH_EXTRA] = data->buf[OS8_DH_EXTRA];

      entrysz = OS8_DI_SIZE + (-os8SXT(le16toh(data->buf[OS8_DH_EXTRA])));
      entries = os8Neg(le16toh(data->buf[OS8_DH_ENTRIES]));
      extra = os8Neg(le16toh(data->buf[OS8_DH_EXTRA]));

      startblk = os8Word(le16toh(data->buf[OS8_DH_START]));

      /*
       * Analyze the current directory segment by finding all the empty
       * descriptors.
       */
      off = OS8_DH_SIZE;

      for (j = 0; j < entries; j++) {
        if (os8Word(le16toh(data->buf[off + OS8_DI_FNAME1])) == 0) {
          emplen[empcount] = os8Neg(le16toh(data->buf[off + OS8_ED_LENGTH]));
          emptotal += emplen[empcount];
          empoff[empcount] = off;
          empcount++;
          emplast = j == (entries - 1);

          off += OS8_ED_SIZE;
        } else off += entrysz;
      }

      /*
       * We want to avoid "stranding" unused directory entries where there
       * is no free space so we apply the following heuristics:
       *
       * 1. If the last directory entry is "empty" and contains at least
       *    50% of the free space, just move this entry to the newly
       *    created directory segment
       *
       * 2. Start the new directory segment at the "empty" entry which would
       *    exceed 50% of the free space.
       */
      target = empoff[empcount - 1];

      if (!emplast || (emplen[empcount - 1] < (emptotal / 2))) {
        uint16_t empty = 0;

        for (j = 0; j < empcount; j++)
          if ((empty + emplen[j]) >= (emptotal / 1)) {
            target = empoff[j];
            break;
          } else empty += emplen[j];
      }

      /*
       * Find the location of the split point and copy all directory entries
       * after this point to the newly created directory segment.
       */
      off = OS8_DH_SIZE;

      for (j = 0; j < entries; j++) {
        uint16_t blks, size;

        if (off == target) {
          split = j + 1;
          buf[OS8_DH_START] = htole16(os8Value(startblk));
        }

        if (os8Word(le16toh(data->buf[off + OS8_DI_FNAME1])) != 0) {
          blks = os8Neg(le16toh(data->buf[off + extra + OS8_DI_LENGTH]));
          size = OS8_DI_SIZE + extra;
        } else {
          blks = os8Neg(le16toh(data->buf[off + OS8_ED_LENGTH]));
          size = OS8_ED_SIZE;
        }

        if (split != 0) {
          uint16_t k;

          for (k = 0; k < size; k++)
            buf[dst++] = data->buf[off + k];

          buf[OS8_DH_ENTRIES]++;
        }
        off += size;
        startblk += blks;
      }

      /*
       * Update the new directory segment
       */
      buf[OS8_DH_ENTRIES] = htole16(os8Value(-buf[OS8_DH_ENTRIES]));

      if (os8WriteBlock(mount, unit, i, buf) == 0)
        return 0;

      /*
       * Update the original directory segment
       */
      data->buf[OS8_DH_ENTRIES] = htole16(os8Value(-(split - 1)));
      data->buf[OS8_DH_NEXT] = htole16(os8Value(i));

      if (os8WriteBlock(mount, unit, segment, NULL) == 0)
        return 0;

      /*
       * Directory segment split complete
       */
      return 1;
    }
  }
  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x660, %rsp            # imm = 0x660
movw %dx, %ax
movb %sil, %cl
movq %rdi, -0x10(%rbp)
movb %cl, -0x11(%rbp)
movw %ax, -0x14(%rbp)
movq -0x10(%rbp), %rax
addq $0x48, %rax
movq %rax, -0x20(%rbp)
movw $0x0, -0x22(%rbp)
movw $0x1, -0x24(%rbp)
movw $0x0, -0x632(%rbp)
movw $0x0, -0x634(%rbp)
movw $0x0, -0x636(%rbp)
movw $0x0, -0x644(%rbp)
movw $0x5, -0x64a(%rbp)
movzwl -0x24(%rbp), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, %ecx
movzwl -0x22(%rbp), %eax
orl %ecx, %eax
movw %ax, -0x22(%rbp)
movq -0x10(%rbp), %rdi
movb -0x11(%rbp), %al
movzwl -0x24(%rbp), %edx
leaq -0x230(%rbp), %rcx
movzbl %al, %esi
callq 0x132f0
cmpl $0x0, %eax
jne 0x14233
movl $0x0, -0x4(%rbp)
jmp 0x14848
movzwl -0x22c(%rbp), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movw %ax, -0x24(%rbp)
movzwl -0x24(%rbp), %eax
cmpl $0x0, %eax
jne 0x141f1
movw $0x1, -0x638(%rbp)
movzwl -0x638(%rbp), %eax
cmpl $0x6, %eax
jg 0x14841
movzwl -0x22(%rbp), %eax
movzwl -0x638(%rbp), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0x14828
movw $0x0, -0x230(%rbp)
movq -0x20(%rbp), %rax
movw 0x18(%rax), %ax
movw %ax, -0x22c(%rbp)
xorl %edi, %edi
callq 0x148e0
movzwl %ax, %edi
callq 0x14890
movw %ax, -0x22a(%rbp)
movq -0x20(%rbp), %rax
movw 0x1c(%rax), %ax
movw %ax, -0x228(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x1c(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x148b0
movzwl %ax, %ecx
xorl %eax, %eax
subl %ecx, %eax
addl $0x5, %eax
movw %ax, -0x63e(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x14(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x63c(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x1c(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x640(%rbp)
movq -0x20(%rbp), %rax
movzwl 0x16(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movw %ax, -0x642(%rbp)
movw $0x5, -0x646(%rbp)
movw $0x0, -0x63a(%rbp)
movzwl -0x63a(%rbp), %eax
movzwl -0x63c(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1447b
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
addl $0x0, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movzwl %ax, %eax
cmpl $0x0, %eax
jne 0x1444b
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, %cx
movzwl -0x636(%rbp), %eax
movw %cx, -0x630(%rbp,%rax,2)
movzwl -0x636(%rbp), %eax
movzwl -0x630(%rbp,%rax,2), %ecx
movzwl -0x632(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x632(%rbp)
movw -0x646(%rbp), %cx
movzwl -0x636(%rbp), %eax
movw %cx, -0x430(%rbp,%rax,2)
movw -0x636(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x636(%rbp)
movzwl -0x63a(%rbp), %eax
movzwl -0x63c(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
sete %al
andb $0x1, %al
movzbl %al, %eax
movw %ax, -0x634(%rbp)
movzwl -0x646(%rbp), %eax
addl $0x2, %eax
movw %ax, -0x646(%rbp)
jmp 0x14462
movzwl -0x63e(%rbp), %ecx
movzwl -0x646(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x646(%rbp)
jmp 0x14464
movw -0x63a(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x63a(%rbp)
jmp 0x14355
movzwl -0x636(%rbp), %eax
subl $0x1, %eax
cltq
movw -0x430(%rbp,%rax,2), %ax
movw %ax, -0x648(%rbp)
cmpw $0x0, -0x634(%rbp)
je 0x144d9
movzwl -0x636(%rbp), %eax
subl $0x1, %eax
cltq
movzwl -0x630(%rbp,%rax,2), %eax
movl %eax, -0x658(%rbp)
movzwl -0x632(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x658(%rbp), %eax
cmpl %ecx, %eax
jge 0x1458c
movw $0x0, -0x64c(%rbp)
movw $0x0, -0x63a(%rbp)
movzwl -0x63a(%rbp), %eax
movzwl -0x636(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1458a
movzwl -0x64c(%rbp), %eax
movzwl -0x63a(%rbp), %ecx
movzwl -0x630(%rbp,%rcx,2), %ecx
addl %ecx, %eax
movl %eax, -0x65c(%rbp)
movzwl -0x632(%rbp), %eax
movl $0x1, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl -0x65c(%rbp), %eax
cmpl %ecx, %eax
jl 0x14552
movzwl -0x63a(%rbp), %eax
movw -0x430(%rbp,%rax,2), %ax
movw %ax, -0x648(%rbp)
jmp 0x1458a
movzwl -0x63a(%rbp), %eax
movzwl -0x630(%rbp,%rax,2), %ecx
movzwl -0x64c(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x64c(%rbp)
jmp 0x14573
movw -0x63a(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x63a(%rbp)
jmp 0x144eb
jmp 0x1458c
movw $0x5, -0x646(%rbp)
movw $0x0, -0x63a(%rbp)
movzwl -0x63a(%rbp), %eax
movzwl -0x63c(%rbp), %ecx
cmpl %ecx, %eax
jge 0x14764
movzwl -0x646(%rbp), %eax
movzwl -0x648(%rbp), %ecx
cmpl %ecx, %eax
jne 0x145f2
movzwl -0x63a(%rbp), %eax
addl $0x1, %eax
movw %ax, -0x644(%rbp)
movzwl -0x642(%rbp), %edi
callq 0x148e0
movzwl %ax, %edi
callq 0x14890
movw %ax, -0x22e(%rbp)
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
addl $0x0, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movzwl %ax, %eax
cmpl $0x0, %eax
je 0x14663
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
movzwl -0x640(%rbp), %edx
addl %edx, %ecx
addl $0x4, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x64e(%rbp)
movzwl -0x640(%rbp), %eax
addl $0x5, %eax
movw %ax, -0x650(%rbp)
jmp 0x14696
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x64e(%rbp)
movw $0x2, -0x650(%rbp)
movzwl -0x644(%rbp), %eax
cmpl $0x0, %eax
je 0x1471f
movw $0x0, -0x652(%rbp)
movzwl -0x652(%rbp), %eax
movzwl -0x650(%rbp), %ecx
cmpl %ecx, %eax
jge 0x1470d
movq -0x20(%rbp), %rax
movzwl -0x646(%rbp), %ecx
movzwl -0x652(%rbp), %edx
addl %edx, %ecx
movslq %ecx, %rcx
movw 0x14(%rax,%rcx,2), %cx
movw -0x64a(%rbp), %ax
movw %ax, %dx
addw $0x1, %dx
movw %dx, -0x64a(%rbp)
movzwl %ax, %eax
movw %cx, -0x230(%rbp,%rax,2)
movw -0x652(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x652(%rbp)
jmp 0x146ab
movw -0x230(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x230(%rbp)
movzwl -0x650(%rbp), %ecx
movzwl -0x646(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x646(%rbp)
movzwl -0x64e(%rbp), %ecx
movzwl -0x642(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x642(%rbp)
movw -0x63a(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x63a(%rbp)
jmp 0x1459e
movzwl -0x230(%rbp), %ecx
xorl %eax, %eax
subl %ecx, %eax
movzwl %ax, %edi
callq 0x148e0
movzwl %ax, %edi
callq 0x14890
movw %ax, -0x230(%rbp)
movq -0x10(%rbp), %rdi
movb -0x11(%rbp), %al
movzwl -0x638(%rbp), %edx
leaq -0x230(%rbp), %rcx
movzbl %al, %esi
callq 0x13450
cmpl $0x0, %eax
jne 0x147b4
movl $0x0, -0x4(%rbp)
jmp 0x14848
movzwl -0x644(%rbp), %ecx
subl $0x1, %ecx
xorl %eax, %eax
subl %ecx, %eax
movzwl %ax, %edi
callq 0x148e0
movzwl %ax, %edi
callq 0x14890
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, 0x14(%rax)
movzwl -0x638(%rbp), %edi
callq 0x148e0
movzwl %ax, %edi
callq 0x14890
movw %ax, %cx
movq -0x20(%rbp), %rax
movw %cx, 0x18(%rax)
movq -0x10(%rbp), %rdi
movb -0x11(%rbp), %al
movzwl -0x14(%rbp), %edx
xorl %ecx, %ecx
movzbl %al, %esi
callq 0x13450
cmpl $0x0, %eax
jne 0x1481f
movl $0x0, -0x4(%rbp)
jmp 0x14848
movl $0x1, -0x4(%rbp)
jmp 0x14848
jmp 0x1482a
movw -0x638(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x638(%rbp)
jmp 0x1425d
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x660, %rsp            # imm = 0x660
popq %rbp
retq
nopw %cs:(%rax,%rax)