// File: /workspace/github_c_makefile_star2_O0/lb3361[P]dosfs/ff.c
// Function: f_getfree
FRESULT f_getfree (
	const TCHAR* path,	/* Logical drive number */
	DWORD* nclst,		/* Pointer to a variable to return number of free clusters */
	FATFS** fatfs		/* Pointer to return pointer to corresponding filesystem object */
)
{
	FRESULT res;
	FATFS *fs;
	DWORD nfree, clst, stat;
	LBA_t sect;
	UINT i;
	FFOBJID obj;


	/* Get logical drive */
	res = mount_volume(&path, &fs, 0);
	if (res == FR_OK) {
		*fatfs = fs;				/* Return ptr to the fs object */
		/* If free_clst is valid, return it without full FAT scan */
		if (fs->free_clst <= fs->n_fatent - 2) {
			*nclst = fs->free_clst;
		} else {
			/* Scan FAT to obtain number of free clusters */
			nfree = 0;
			if (fs->fs_type == FS_FAT12) {	/* FAT12: Scan bit field FAT entries */
				clst = 2; obj.fs = fs;
				do {
					stat = get_fat(&obj, clst);
					if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
					if (stat == 1) { res = FR_INT_ERR; break; }
					if (stat == 0) nfree++;
				} while (++clst < fs->n_fatent);
			} else {
#if FF_FS_EXFAT
				if (fs->fs_type == FS_EXFAT) {	/* exFAT: Scan allocation bitmap */
					BYTE bm;
					UINT b;

					clst = fs->n_fatent - 2;	/* Number of clusters */
					sect = fs->bitbase;			/* Bitmap sector */
					i = 0;						/* Offset in the sector */
					do {	/* Counts numbuer of bits with zero in the bitmap */
						if (i == 0) {
							res = move_window(fs, sect++);
							if (res != FR_OK) break;
						}
						for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
							if (!(bm & 1)) nfree++;
							bm >>= 1;
						}
						i = (i + 1) % SS(fs);
					} while (clst);
				} else
#endif
				{	/* FAT16/32: Scan WORD/DWORD FAT entries */
					clst = fs->n_fatent;	/* Number of entries */
					sect = fs->fatbase;		/* Top of the FAT */
					i = 0;					/* Offset in the sector */
					do {	/* Counts numbuer of entries with zero in the FAT */
						if (i == 0) {
							res = move_window(fs, sect++);
							if (res != FR_OK) break;
						}
						if (fs->fs_type == FS_FAT16) {
							if (ld_word(fs->win + i) == 0) nfree++;
							i += 2;
						} else {
							if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
							i += 4;
						}
						i %= SS(fs);
					} while (--clst);
				}
			}
			*nclst = nfree;			/* Return the free clusters */
			fs->free_clst = nfree;	/* Now free_clst is valid */
			fs->fsi_flag |= 1;		/* FAT32: FSInfo is to be updated */
		}
	}

	LEAVE_FF(fs, res);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
leaq -0x8(%rbp), %rdi
leaq -0x28(%rbp), %rsi
xorl %edx, %edx
callq 0x4940
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0x937e
movq -0x28(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x28(%rbp), %rax
movl 0x24(%rax), %eax
movq -0x28(%rbp), %rcx
movl 0x28(%rcx), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
ja 0x9125
movq -0x28(%rbp), %rax
movl 0x24(%rax), %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
jmp 0x937c
movl $0x0, -0x2c(%rbp)
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x1, %eax
jne 0x919c
movl $0x2, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x78(%rbp)
movl -0x30(%rbp), %esi
leaq -0x78(%rbp), %rdi
callq 0x6560
movl %eax, -0x34(%rbp)
cmpl $-0x1, -0x34(%rbp)
jne 0x9165
movl $0x1, -0x1c(%rbp)
jmp 0x9197
cmpl $0x1, -0x34(%rbp)
jne 0x9174
movl $0x2, -0x1c(%rbp)
jmp 0x9197
cmpl $0x0, -0x34(%rbp)
jne 0x9183
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x9185
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rcx
cmpl 0x28(%rcx), %eax
jb 0x9147
jmp 0x935b
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x4, %eax
jne 0x9285
movq -0x28(%rbp), %rax
movl 0x28(%rax), %eax
subl $0x2, %eax
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
cmpl $0x0, -0x44(%rbp)
jne 0x91fa
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq %rsi, %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
callq 0x6480
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x91f8
jmp 0x9280
jmp 0x91fa
movl $0x8, -0x80(%rbp)
movq -0x28(%rbp), %rax
movl -0x44(%rbp), %ecx
movb 0x60(%rax,%rcx), %al
movb %al, -0x79(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x80(%rbp)
movb %al, -0x81(%rbp)
je 0x922a
cmpl $0x0, -0x30(%rbp)
setne %al
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %al
testb $0x1, %al
jne 0x9236
jmp 0x9268
movzbl -0x79(%rbp), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x924b
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movzbl -0x79(%rbp), %eax
sarl %eax
movb %al, -0x79(%rbp)
movl -0x80(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x80(%rbp)
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x920f
movl -0x44(%rbp), %eax
addl $0x1, %eax
andl $0x1ff, %eax            # imm = 0x1FF
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x30(%rbp)
jne 0x91cc
jmp 0x9359
movq -0x28(%rbp), %rax
movl 0x28(%rax), %eax
movl %eax, -0x30(%rbp)
movq -0x28(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
cmpl $0x0, -0x44(%rbp)
jne 0x92d0
movq -0x28(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq %rsi, %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
callq 0x6480
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x92ce
jmp 0x9357
jmp 0x92d0
movq -0x28(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x2, %eax
jne 0x930b
movq -0x28(%rbp), %rdi
addq $0x60, %rdi
movl -0x44(%rbp), %eax
addq %rax, %rdi
callq 0x9390
movzwl %ax, %eax
cmpl $0x0, %eax
jne 0x9300
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x44(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x44(%rbp)
jmp 0x933a
movq -0x28(%rbp), %rdi
addq $0x60, %rdi
movl -0x44(%rbp), %eax
addq %rax, %rdi
callq 0x6510
andl $0xfffffff, %eax        # imm = 0xFFFFFFF
cmpl $0x0, %eax
jne 0x9331
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x44(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
andl $0x1ff, %eax            # imm = 0x1FF
movl %eax, -0x44(%rbp)
movl -0x30(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x30(%rbp)
cmpl $0x0, %eax
jne 0x92a2
jmp 0x9359
jmp 0x935b
movl -0x2c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
movl -0x2c(%rbp), %ecx
movq -0x28(%rbp), %rax
movl %ecx, 0x24(%rax)
movq -0x28(%rbp), %rax
movzbl 0x4(%rax), %ecx
orl $0x1, %ecx
movb %cl, 0x4(%rax)
jmp 0x937e
movl -0x1c(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw (%rax,%rax)