// File: /workspace/github_c_makefile_star2_O2/lb3361[P]dosfs/ff.c
// Function: f_forward
FRESULT f_forward (
	FIL* fp, 						/* Pointer to the file object */
	UINT (*func)(const BYTE*,UINT),	/* Pointer to the streaming function */
	UINT btf,						/* Number of bytes to forward */
	UINT* bf						/* Pointer to number of bytes forwarded */
)
{
	FRESULT res;
	FATFS *fs;
	DWORD clst;
	LBA_t sect;
	FSIZE_t remain;
	UINT rcnt, csect;
	BYTE *dbuf;


	*bf = 0;	/* Clear transfer byte counter */
	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
	if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */

	remain = fp->obj.objsize - fp->fptr;
	if (btf > remain) btf = (UINT)remain;			/* Truncate btf by remaining bytes */

	for ( ;  btf && (*func)(0, 0);					/* Repeat until all data transferred or stream goes busy */
		fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
		csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));	/* Sector offset in the cluster */
		if (fp->fptr % SS(fs) == 0) {				/* On the sector boundary? */
			if (csect == 0) {						/* On the cluster boundary? */
				clst = (fp->fptr == 0) ?			/* On the top of the file? */
					fp->obj.sclust : get_fat(&fp->obj, fp->clust);
				if (clst <= 1) ABORT(fs, FR_INT_ERR);
				if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
				fp->clust = clst;					/* Update current cluster */
			}
		}
		sect = clst2sect(fs, fp->clust);			/* Get current data sector */
		if (sect == 0) ABORT(fs, FR_INT_ERR);
		sect += csect;
#if FF_FS_TINY
		if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR);	/* Move sector window to the file data */
		dbuf = fs->win;
#else
		if (fp->sect != sect) {		/* Fill sector cache with file data */
#if !FF_FS_READONLY
			if (fp->flag & FA_DIRTY) {		/* Write-back dirty sector cache */
				if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
				fp->flag &= (BYTE)~FA_DIRTY;
			}
#endif
			if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
		}
		dbuf = fp->buf;
#endif
		fp->sect = sect;
		rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);	/* Number of bytes remains in the sector */
		if (rcnt > btf) rcnt = btf;					/* Clip it by btr if needed */
		rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt);	/* Forward the file data */
		if (rcnt == 0) ABORT(fs, FR_INT_ERR);
	}

	LEAVE_FF(fs, FR_OK);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movq %rcx, %r14
movl %edx, %ebp
movq %rsi, %r15
movq %rdi, %rbx
andl $0x0, (%rcx)
leaq 0x20(%rsp), %rsi
callq 0x607b
movl %eax, %r13d
testl %eax, %eax
jne 0x8a7f
movzbl 0x31(%rbx), %r13d
testl %r13d, %r13d
jne 0x8a7f
testb $0x1, 0x30(%rbx)
jne 0x8929
pushq $0x7
popq %r13
jmp 0x8a7f
movq 0x10(%rbx), %r12
subq 0x38(%rbx), %r12
movl %ebp, %eax
cmpq %rax, %r12
cmovael %ebp, %r12d
movq 0x20(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0x60(%rbx), %rax
movq %rax, 0x10(%rsp)
movq %r15, 0x18(%rsp)
xorl %r13d, %r13d
testl %r12d, %r12d
je 0x8a7f
xorl %edi, %edi
xorl %esi, %esi
callq *%r15
testl %eax, %eax
je 0x8a7f
movq 0x38(%rbx), %rax
movq %rax, %rcx
shrq $0x9, %rcx
movq 0x8(%rsp), %rdx
movzwl 0xa(%rdx), %edx
decl %edx
movl %eax, %esi
andl $0x1ff, %esi            # imm = 0x1FF
andl %edx, %ecx
movl %ecx, %r15d
orq %r15, %rsi
jne 0x89a9
testq %rax, %rax
je 0x89ae
movl 0x40(%rbx), %esi
movq %rbx, %rdi
callq 0x5c48
movl %eax, %esi
jmp 0x89b1
movl 0x40(%rbx), %esi
jmp 0x89c6
movl 0xc(%rbx), %esi
cmpl $0x2, %esi
jb 0x8a72
cmpl $-0x1, %esi
je 0x8a6b
movl %esi, 0x40(%rbx)
movq 0x8(%rsp), %rdi
callq 0x5e21
movb $0x2, %r13b
testq %rax, %rax
je 0x8a75
movq %rax, %rbp
addq %r15, %rbp
movq 0x48(%rbx), %rdx
cmpq %rbp, %rdx
movq 0x18(%rsp), %r15
je 0x8a31
cmpb $0x0, 0x30(%rbx)
jns 0x8a14
movq 0x8(%rsp), %rax
movzbl 0x1(%rax), %edi
movq 0x10(%rsp), %rsi
pushq $0x1
popq %rcx
callq 0x28af
testl %eax, %eax
jne 0x8a6b
andb $0x7f, 0x30(%rbx)
movq 0x8(%rsp), %rax
movzbl 0x1(%rax), %edi
movq 0x10(%rsp), %rsi
movq %rbp, %rdx
pushq $0x1
popq %rcx
callq 0x283b
testl %eax, %eax
jne 0x8a6b
movq %rbp, 0x48(%rbx)
movq 0x38(%rbx), %rdi
andl $0x1ff, %edi            # imm = 0x1FF
movl $0x200, %esi            # imm = 0x200
subl %edi, %esi
cmpl %r12d, %esi
jb 0x8a4e
movl %r12d, %esi
addq 0x10(%rsp), %rdi
callq *%r15
testl %eax, %eax
je 0x8a75
movl %eax, %ecx
addq %rcx, 0x38(%rbx)
addl %eax, (%r14)
subl %eax, %r12d
jmp 0x8952
movb $0x1, %r13b
pushq $0x1
jmp 0x8a77
movb $0x2, %r13b
pushq $0x2
popq %rax
movb %r13b, 0x31(%rbx)
movl %eax, %r13d
movl %r13d, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq