// File: /workspace/github_c_makefile_star2_O0/gadget114514[P]fatfs-example/fatfs/source/ff.c
// Function: f_lseek
FRESULT f_lseek (
	FIL* fp,		/* Pointer to the file object */
	FSIZE_t ofs		/* File pointer from top of file */
)
{
	FRESULT res;
	FATFS *fs;
	DWORD clst, bcs, nsect;
	FSIZE_t ifptr;
#if FF_USE_FASTSEEK
	DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
#endif

	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
	if (res == FR_OK) res = (FRESULT)fp->err;
#if FF_FS_EXFAT && !FF_FS_READONLY
	if (res == FR_OK && fs->fs_type == FS_EXFAT) {
		res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
	}
#endif
	if (res != FR_OK) LEAVE_FF(fs, res);

#if FF_USE_FASTSEEK
	if (fp->cltbl) {	/* Fast seek */
		if (ofs == CREATE_LINKMAP) {	/* Create CLMT */
			tbl = fp->cltbl;
			tlen = *tbl++; ulen = 2;	/* Given table size and required table size */
			cl = fp->obj.sclust;		/* Origin of the chain */
			if (cl != 0) {
				do {
					/* Get a fragment */
					tcl = cl; ncl = 0; ulen += 2;	/* Top, length and used items */
					do {
						pcl = cl; ncl++;
						cl = get_fat(&fp->obj, cl);
						if (cl <= 1) ABORT(fs, FR_INT_ERR);
						if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
					} while (cl == pcl + 1);
					if (ulen <= tlen) {		/* Store the length and top of the fragment */
						*tbl++ = ncl; *tbl++ = tcl;
					}
				} while (cl < fs->n_fatent);	/* Repeat until end of chain */
			}
			*fp->cltbl = ulen;	/* Number of items used */
			if (ulen <= tlen) {
				*tbl = 0;		/* Terminate table */
			} else {
				res = FR_NOT_ENOUGH_CORE;	/* Given table size is smaller than required */
			}
		} else {						/* Fast seek */
			if (ofs > fp->obj.objsize) ofs = fp->obj.objsize;	/* Clip offset at the file size */
			fp->fptr = ofs;				/* Set file pointer */
			if (ofs > 0) {
				fp->clust = clmt_clust(fp, ofs - 1);
				dsc = clst2sect(fs, fp->clust);
				if (dsc == 0) ABORT(fs, FR_INT_ERR);
				dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
				if (fp->fptr % SS(fs) && dsc != fp->sect) {	/* Refill sector cache if needed */
#if !FF_FS_TINY
#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, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Load current sector */
#endif
					fp->sect = dsc;
				}
			}
		}
	} else
#endif

	/* Normal Seek */
	{
#if FF_FS_EXFAT
		if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF;	/* Clip at 4 GiB - 1 if at FATxx */
#endif
		if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) {	/* In read-only mode, clip offset with the file size */
			ofs = fp->obj.objsize;
		}
		ifptr = fp->fptr;
		fp->fptr = nsect = 0;
		if (ofs > 0) {
			bcs = (DWORD)fs->csize * SS(fs);	/* Cluster size (byte) */
			if (ifptr > 0 &&
				(ofs - 1) / bcs >= (ifptr - 1) / bcs) {	/* When seek to same or following cluster, */
				fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1);	/* start from the current cluster */
				ofs -= fp->fptr;
				clst = fp->clust;
			} else {									/* When seek to back cluster, */
				clst = fp->obj.sclust;					/* start from the first cluster */
#if !FF_FS_READONLY
				if (clst == 0) {						/* If no cluster chain, create a new chain */
					clst = create_chain(&fp->obj, 0);
					if (clst == 1) ABORT(fs, FR_INT_ERR);
					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
					fp->obj.sclust = clst;
				}
#endif
				fp->clust = clst;
			}
			if (clst != 0) {
				while (ofs > bcs) {						/* Cluster following loop */
					ofs -= bcs; fp->fptr += bcs;
#if !FF_FS_READONLY
					if (fp->flag & FA_WRITE) {			/* Check if in write mode or not */
						if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) {	/* No FAT chain object needs correct objsize to generate FAT value */
							fp->obj.objsize = fp->fptr;
							fp->flag |= FA_MODIFIED;
						}
						clst = create_chain(&fp->obj, clst);	/* Follow chain with forceed stretch */
						if (clst == 0) {				/* Clip file size in case of disk full */
							ofs = 0; break;
						}
					} else
#endif
					{
						clst = get_fat(&fp->obj, clst);	/* Follow cluster chain if not in write mode */
					}
					if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
					if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
					fp->clust = clst;
				}
				fp->fptr += ofs;
				if (ofs % SS(fs)) {
					nsect = clst2sect(fs, clst);	/* Current sector */
					if (nsect == 0) ABORT(fs, FR_INT_ERR);
					nsect += (DWORD)(ofs / SS(fs));
				}
			}
		}
		if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) {	/* Set file change flag if the file size is extended */
			fp->obj.objsize = fp->fptr;
			fp->flag |= FA_MODIFIED;
		}
		if (fp->fptr % SS(fs) && nsect != fp->sect) {	/* Fill sector cache if needed */
#if !FF_FS_TINY
#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, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);	/* Fill sector cache */
#endif
			fp->sect = nsect;
		}
	}

	LEAVE_FF(fs, res);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x2fe0
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0x3b71
movq -0x10(%rbp), %rax
movzbl 0x21(%rax), %eax
movl %eax, -0x1c(%rbp)
cmpl $0x0, -0x1c(%rbp)
je 0x3b82
movl -0x1c(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x3f08
movq -0x18(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jbe 0x3bac
movq -0x10(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
jne 0x3bac
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x48(%rbp)
movq $0x0, -0x40(%rbp)
movq -0x10(%rbp), %rax
movq $0x0, 0x28(%rax)
cmpq $0x0, -0x18(%rbp)
jbe 0x3e0c
movq -0x28(%rbp), %rax
movzwl 0xa(%rax), %eax
shlq $0x9, %rax
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x48(%rbp)
jbe 0x3c5e
movq -0x18(%rbp), %rax
subq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x38(%rbp)
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
subq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x38(%rbp)
movq %rax, %rcx
movq -0x50(%rbp), %rax
cmpq %rcx, %rax
jb 0x3c5e
movq -0x48(%rbp), %rcx
subq $0x1, %rcx
movq -0x38(%rbp), %rax
subq $0x1, %rax
xorq $-0x1, %rax
andq %rax, %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x28(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rcx
movq -0x18(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x30(%rbp)
jmp 0x3cd4
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x3cc8
movq -0x10(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3540
movq %rax, -0x30(%rbp)
cmpq $0x1, -0x30(%rbp)
jne 0x3c9d
movq -0x10(%rbp), %rax
movb $0x2, 0x21(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x3f08
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, -0x30(%rbp)
jne 0x3cbc
movq -0x10(%rbp), %rax
movb $0x1, 0x21(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x3f08
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
cmpq $0x0, -0x30(%rbp)
je 0x3e0a
jmp 0x3ce1
movq -0x18(%rbp), %rax
cmpq -0x38(%rbp), %rax
jbe 0x3dac
movq -0x38(%rbp), %rcx
movq -0x18(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x18(%rbp)
movq -0x38(%rbp), %rcx
movq -0x10(%rbp), %rax
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
movq -0x10(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x3d42
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x3540
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
jne 0x3d40
movq $0x0, -0x18(%rbp)
jmp 0x3dac
jmp 0x3d53
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x29e0
movq %rax, -0x30(%rbp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpq %rax, -0x30(%rbp)
jne 0x3d72
movq -0x10(%rbp), %rax
movb $0x1, 0x21(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x3f08
cmpq $0x1, -0x30(%rbp)
jbe 0x3d87
movq -0x30(%rbp), %rax
movq -0x28(%rbp), %rcx
cmpq 0x20(%rcx), %rax
jb 0x3d9b
movq -0x10(%rbp), %rax
movb $0x2, 0x21(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x3f08
movq -0x30(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x30(%rax)
jmp 0x3ce1
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
addq 0x28(%rax), %rcx
movq %rcx, 0x28(%rax)
movq -0x18(%rbp), %rax
andq $0x1ff, %rax            # imm = 0x1FF
cmpq $0x0, %rax
je 0x3e08
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x2bd0
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x3df8
movq -0x10(%rbp), %rax
movb $0x2, 0x21(%rax)
movl $0x2, -0x4(%rbp)
jmp 0x3f08
movq -0x18(%rbp), %rax
shrq $0x9, %rax
addq -0x40(%rbp), %rax
movq %rax, -0x40(%rbp)
jmp 0x3e0a
jmp 0x3e0c
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x10(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jbe 0x3e3c
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x18(%rax)
movq -0x10(%rbp), %rax
movzbl 0x20(%rax), %ecx
orl $0x40, %ecx
movb %cl, 0x20(%rax)
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
andq $0x1ff, %rax            # imm = 0x1FF
cmpq $0x0, %rax
je 0x3f02
movq -0x40(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x38(%rcx), %rax
je 0x3f02
movq -0x10(%rbp), %rax
movzbl 0x20(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0x3ec0
movq -0x28(%rbp), %rax
movb 0x1(%rax), %al
movq -0x10(%rbp), %rsi
addq $0x50, %rsi
movq -0x10(%rbp), %rcx
movq 0x38(%rcx), %rdx
movl $0x1, %ecx
movzbl %al, %edi
callq 0x14c0
cmpl $0x0, %eax
je 0x3eb2
movq -0x10(%rbp), %rax
movb $0x1, 0x21(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x3f08
movq -0x10(%rbp), %rax
movzbl 0x20(%rax), %ecx
andl $0x7f, %ecx
movb %cl, 0x20(%rax)
movq -0x28(%rbp), %rax
movb 0x1(%rax), %al
movq -0x10(%rbp), %rsi
addq $0x50, %rsi
movq -0x40(%rbp), %rdx
movl $0x1, %ecx
movzbl %al, %edi
callq 0x1450
cmpl $0x0, %eax
je 0x3ef6
movq -0x10(%rbp), %rax
movb $0x1, 0x21(%rax)
movl $0x1, -0x4(%rbp)
jmp 0x3f08
movq -0x40(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x38(%rax)
movl -0x1c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)