// File: /workspace/github_c_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %r15
movq %rsi, %rbx
leaq 0x10(%rsp), %rax
movq %rdi, (%rax)
leaq 0x8(%rsp), %rsi
movq %rax, %rdi
xorl %edx, %edx
callq 0x4c82
testl %eax, %eax
jne 0x81d3
movq 0x8(%rsp), %r14
movq %r14, (%r15)
movl 0x24(%r14), %eax
movl 0x28(%r14), %ebp
leal -0x2(%rbp), %r13d
cmpl %r13d, %eax
jbe 0x80c1
movzbl (%r14), %eax
cmpl $0x4, %eax
je 0x80ca
cmpl $0x1, %eax
jne 0x813e
leaq 0x18(%rsp), %r15
movq %r14, (%r15)
movl $0x2, %ebp
xorl %r12d, %r12d
movq %r15, %rdi
movl %ebp, %esi
callq 0x6363
testl %eax, %eax
je 0x80b1
cmpl $-0x1, %eax
je 0x81e9
cmpl $0x1, %eax
jne 0x80b4
jmp 0x81e2
incl %r12d
incl %ebp
cmpl 0x28(%r14), %ebp
jb 0x8090
jmp 0x81c5
movl %eax, (%rbx)
xorl %eax, %eax
jmp 0x81d3
movq 0x50(%r14), %r15
xorl %r12d, %r12d
xorl %ebp, %ebp
testl %ebp, %ebp
jne 0x80ed
movq %r14, %rdi
movq %r15, %rsi
callq 0x6314
testl %eax, %eax
jne 0x81c7
incq %r15
testl %r13d, %r13d
setne %al
je 0x812d
movl %ebp, %eax
movb 0x60(%r14,%rax), %cl
leal -0x1(%r13), %edx
xorl %esi, %esi
movl %r12d, %eax
movl %ecx, %edi
notb %dil
andb $0x1, %dil
movzbl %dil, %r12d
addl %eax, %r12d
cmpl %esi, %edx
setne %al
leal 0x1(%rsi), %edi
cmpl $0x7, %esi
je 0x812a
shrb %cl
cmpl %esi, %edx
movl %edi, %esi
jne 0x8102
subl %edi, %r13d
incl %ebp
andl $0x1ff, %ebp            # imm = 0x1FF
testb %al, %al
jne 0x80d3
jmp 0x81c5
movq 0x38(%r14), %r15
xorl %r12d, %r12d
xorl %r13d, %r13d
testl %r13d, %r13d
jne 0x815f
movq %r14, %rdi
movq %r15, %rsi
callq 0x6314
testl %eax, %eax
jne 0x81c7
incq %r15
cmpb $0x2, (%r14)
movl %r13d, %eax
jne 0x817c
movb 0x60(%r14,%rax), %cl
orb 0x61(%r14,%rax), %cl
sete %al
movl $0x2, %ecx
jmp 0x81b1
movzbl 0x63(%r14,%rax), %ecx
movzbl 0x62(%r14,%rax), %edx
shll $0x10, %ecx
shll $0x8, %edx
orl %ecx, %edx
movzbl 0x61(%r14,%rax), %ecx
orl %edx, %ecx
shll $0x8, %ecx
movzbl 0x60(%r14,%rax), %eax
andl $0xfffff00, %ecx        # imm = 0xFFFFF00
orl %eax, %ecx
sete %al
movl $0x4, %ecx
addl %ecx, %r13d
movzbl %al, %eax
addl %eax, %r12d
andl $0x1ff, %r13d           # imm = 0x1FF
decl %ebp
jne 0x8148
xorl %eax, %eax
movl %r12d, (%rbx)
movl %r12d, 0x24(%r14)
orb $0x1, 0x4(%r14)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x2, %eax
jmp 0x81c7
movl $0x1, %eax
jmp 0x81c7