// File: /workspace/github_c_makefile_star2_O0/simh[P]simtools/converters/fsio/os8.c
// Function: validate
static int validate(
  struct mountedFS *mount,
  uint8_t unit,
  uint16_t *files,
  uint16_t *freeblks,
  uint16_t *addinfo
)
{
  struct OS8data *data = &mount->os8data;
  unsigned int dirblk = OS8_DSSTART;
  uint8_t seen[OS8_DSLAST + 1];
  uint16_t extraVal;

  memset(seen, 0, sizeof(seen));
  
  do {
    uint16_t i, entrysz, entries, flagwd, extra, startblk, off = OS8_DH_SIZE;

    /*
     * If we've already seen this directory segment, there must be a loop
     */
    if (seen[dirblk] != 0)
      return 0;

    if (!os8BlockPresent(mount, unit, dirblk) ||
        !os8ReadBlock(mount, unit, dirblk, NULL))
      return 0;

    seen[dirblk] = 1;

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

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

    /*
     * The number of additional information words MUST be the same in all
     * directory segments.
     */
    if (dirblk == OS8_DSSTART) {
      extraVal = extra;
      *addinfo = extra;
    }

    if (extraVal != extra)
      return 0;

    /*
     * Up to 077 extra words may be allocated to each directory entry.
     */
    if ((extra & 07700) != 0)
      return 0;

    /*
     * The flag word must be either 0 or in the range 01400 - 01777.
     */
    if ((flagwd != 0) && ((flagwd & 01400) != 01400))
      return 0;

    /*
     * There must be at least one directory entry (an empty file occupying
     * all the space) and, at maximum, alternating permanent and empty
     * entries (256 / ((N + 5) + 2)) * 2.
     */
    if ((entries == 0) || (entries > ((256 / (extra + 7))) * 2))
      return 0;

    /*
     * Scan the directory checking for valid block addresses.
     */
    for (i = 0; i < entries; i++) {
      uint16_t length;

      if (os8Word(le16toh(data->buf[off + OS8_DI_FNAME1])) != 0) {
        length = os8Neg(le16toh(data->buf[off + extra + OS8_DI_LENGTH]));
        off += entrysz;
        *files += 1;
      } else {
        length = os8Neg(le16toh(data->buf[off + OS8_ED_LENGTH]));
        off += OS8_ED_SIZE;
        *freeblks += length;
      }
      startblk += length;

      /*
       * Make sure the block addresses are valid for this disk device
       */
      if (startblk > data->device->blocks[unit])
        return 0;
    }

    dirblk = os8Word(le16toh(data->buf[OS8_DH_NEXT]));

    if ((dirblk != 0) && ((dirblk < OS8_DSSTART) || (dirblk > OS8_DSLAST)))
      return 0;

  } while (dirblk != 0);

  return 1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movb %sil, %al
movq %rdi, -0x10(%rbp)
movb %al, -0x11(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq -0x10(%rbp), %rax
addq $0x48, %rax
movq %rax, -0x38(%rbp)
movl $0x1, -0x3c(%rbp)
leaq -0x43(%rbp), %rdi
xorl %esi, %esi
movl $0x7, %edx
callq 0x3170
movw $0x5, -0x54(%rbp)
movl -0x3c(%rbp), %eax
movzbl -0x43(%rbp,%rax), %eax
cmpl $0x0, %eax
je 0x16b90
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movq -0x10(%rbp), %rdi
movb -0x11(%rbp), %al
movl -0x3c(%rbp), %edx
movzbl %al, %esi
callq 0x132a0
cmpl $0x0, %eax
je 0x16bc0
movq -0x10(%rbp), %rdi
movb -0x11(%rbp), %al
movl -0x3c(%rbp), %edx
xorl %ecx, %ecx
movzbl %al, %esi
callq 0x132f0
cmpl $0x0, %eax
jne 0x16bcc
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movl -0x3c(%rbp), %eax
movb $0x1, -0x43(%rbp,%rax)
movq -0x38(%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, -0x4a(%rbp)
movq -0x38(%rbp), %rax
movzwl 0x14(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x4c(%rbp)
movq -0x38(%rbp), %rax
movzwl 0x1a(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movw %ax, -0x4e(%rbp)
movq -0x38(%rbp), %rax
movzwl 0x1c(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x50(%rbp)
movq -0x38(%rbp), %rax
movzwl 0x16(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movw %ax, -0x52(%rbp)
cmpl $0x1, -0x3c(%rbp)
jne 0x16c74
movw -0x50(%rbp), %ax
movw %ax, -0x46(%rbp)
movw -0x50(%rbp), %cx
movq -0x30(%rbp), %rax
movw %cx, (%rax)
movzwl -0x46(%rbp), %eax
movzwl -0x50(%rbp), %ecx
cmpl %ecx, %eax
je 0x16c8c
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movzwl -0x50(%rbp), %eax
andl $0xfc0, %eax            # imm = 0xFC0
cmpl $0x0, %eax
je 0x16ca6
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movzwl -0x4e(%rbp), %eax
cmpl $0x0, %eax
je 0x16ccb
movzwl -0x4e(%rbp), %eax
andl $0x300, %eax            # imm = 0x300
cmpl $0x300, %eax            # imm = 0x300
je 0x16ccb
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movzwl -0x4c(%rbp), %eax
cmpl $0x0, %eax
je 0x16cf5
movzwl -0x4c(%rbp), %eax
movl %eax, -0x5c(%rbp)
movzwl -0x50(%rbp), %ecx
addl $0x7, %ecx
movl $0x100, %eax            # imm = 0x100
cltd
idivl %ecx
movl %eax, %ecx
movl -0x5c(%rbp), %eax
shll %ecx
cmpl %ecx, %eax
jle 0x16d01
movl $0x0, -0x4(%rbp)
jmp 0x16e51
movw $0x0, -0x48(%rbp)
movzwl -0x48(%rbp), %eax
movzwl -0x4c(%rbp), %ecx
cmpl %ecx, %eax
jge 0x16e08
movq -0x38(%rbp), %rax
movzwl -0x54(%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 0x16d86
movq -0x38(%rbp), %rax
movzwl -0x54(%rbp), %ecx
movzwl -0x50(%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, -0x56(%rbp)
movzwl -0x4a(%rbp), %ecx
movzwl -0x54(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x54(%rbp)
movq -0x20(%rbp), %rax
movzwl (%rax), %ecx
addl $0x1, %ecx
movw %cx, (%rax)
jmp 0x16dc5
movq -0x38(%rbp), %rax
movzwl -0x54(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movzwl 0x14(%rax,%rcx,2), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14860
movw %ax, -0x56(%rbp)
movzwl -0x54(%rbp), %eax
addl $0x2, %eax
movw %ax, -0x54(%rbp)
movzwl -0x56(%rbp), %edx
movq -0x28(%rbp), %rax
movzwl (%rax), %ecx
addl %edx, %ecx
movw %cx, (%rax)
movzwl -0x56(%rbp), %ecx
movzwl -0x52(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x52(%rbp)
movzwl -0x52(%rbp), %eax
movq -0x38(%rbp), %rcx
movq 0x8(%rcx), %rcx
movzbl -0x11(%rbp), %edx
movzwl 0x20(%rcx,%rdx,2), %ecx
cmpl %ecx, %eax
jle 0x16df5
movl $0x0, -0x4(%rbp)
jmp 0x16e51
jmp 0x16df7
movw -0x48(%rbp), %ax
addw $0x1, %ax
movw %ax, -0x48(%rbp)
jmp 0x16d07
movq -0x38(%rbp), %rax
movzwl 0x18(%rax), %edi
callq 0x14890
movzwl %ax, %edi
callq 0x14f90
movzwl %ax, %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
je 0x16e3e
cmpl $0x1, -0x3c(%rbp)
jb 0x16e35
cmpl $0x6, -0x3c(%rbp)
jbe 0x16e3e
movl $0x0, -0x4(%rbp)
jmp 0x16e51
jmp 0x16e40
cmpl $0x0, -0x3c(%rbp)
jne 0x16b71
movl $0x1, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nopw (%rax,%rax)