// File: /workspace/github_c_makefile_star2_O3/dlbeer[P]ufat/ufat.c
// Function: ufat_cache_open
int ufat_cache_open(struct ufat *uf, ufat_block_t blk_index, int skip_read)
{
	unsigned int i;
	int oldest = -1;
	int free = -1;
	int err;
	unsigned int oldest_age = 0;

	/* Scan the cache, looking for:
	 *
	 *   (a) the item, if we already have it.
	 *   (b) a free slot, if one exists.
	 *   (c) the oldest cache item.
	 */
	for (i = 0; i < uf->cache_size; i++) {
		struct ufat_cache_desc *d = &uf->cache_desc[i];
		unsigned int age = uf->next_seq - d->seq;

		if ((d->flags & UFAT_CACHE_FLAG_PRESENT) &&
		    d->index == blk_index) {
			d->seq = uf->next_seq++;
			uf->stat.cache_hit++;
			return i;
		}

		if (!(d->flags & UFAT_CACHE_FLAG_PRESENT))
			free = i;

		if (oldest < 0 || age > oldest_age) {
			oldest_age = age;
			oldest = i;
		}
	}

	/* We don't have the item. Find a place to put it. */
	if (free >= 0) {
		i = free;
	} else {
		err = cache_flush(uf, oldest);
		if (err < 0)
			return err;

		i = oldest;
	}

	if (skip_read == 0) {
		/* Read it in */
		err = uf->dev->read(uf->dev, blk_index, 1,
				    ufat_cache_data(uf, i));
		if (err < 0) {
			uf->cache_desc[i].flags = 0;
			return err;
		}

		uf->stat.read++;
		uf->stat.read_blocks++;
	} else
		memset(ufat_cache_data(uf, i), 0,
		       1 << uf->dev->log2_block_size);

	struct ufat_cache_desc *d = &uf->cache_desc[i];
	d->flags = UFAT_CACHE_FLAG_PRESENT;
	d->index = blk_index;
	d->seq = uf->next_seq++;

	uf->stat.cache_miss++;

	return i;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movl %edx, %r15d
movq %rsi, %r14
movq %rdi, %rbx
movl 0x74(%rdi), %eax
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
testq %rax, %rax
je 0x1b38
movl 0x70(%rbx), %edx
leaq 0x88(%rbx), %rsi
xorl %ecx, %ecx
xorl %edi, %edi
movl $0xffffffff, %r13d      # imm = 0xFFFFFFFF
movl %edx, %r8d
subl -0x4(%rsi), %r8d
testb $0x2, -0x8(%rsi)
jne 0x1b05
movl %ecx, %r13d
jmp 0x1b0e
cmpq %r14, (%rsi)
je 0x1bd7
testl %r12d, %r12d
sets %r9b
cmpl %edi, %r8d
seta %r10b
orb %r9b, %r10b
cmovnel %r8d, %edi
cmovnel %ecx, %r12d
incq %rcx
addq $0x10, %rsi
cmpq %rcx, %rax
jne 0x1af3
testl %r13d, %r13d
jns 0x1b4e
movq %rbx, %rdi
movl %r12d, %esi
callq 0x198c
movl %r12d, %r13d
testl %eax, %eax
js 0x1bfb
testl %r15d, %r15d
je 0x1b7b
movq (%rbx), %rax
movb (%rax), %cl
movl %r13d, %eax
shll %cl, %eax
leaq (%rbx,%rax), %rdi
addq $0x180, %rdi            # imm = 0x180
movl $0x1, %eax
shll %cl, %eax
movslq %eax, %rdx
xorl %esi, %esi
callq 0x1110
jmp 0x1ba5
movq (%rbx), %rdi
movb (%rdi), %cl
movl %r13d, %eax
shll %cl, %eax
leaq (%rbx,%rax), %rcx
addq $0x180, %rcx            # imm = 0x180
movl $0x1, %edx
movq %r14, %rsi
callq *0x8(%rdi)
testl %eax, %eax
js 0x1be7
incl 0x8(%rbx)
incl 0x10(%rbx)
movl %r13d, %eax
shlq $0x4, %rax
movl $0x2, 0x80(%rbx,%rax)
movq %r14, 0x88(%rbx,%rax)
movl 0x70(%rbx), %ecx
leal 0x1(%rcx), %edx
movl %edx, 0x70(%rbx)
movl %ecx, 0x84(%rbx,%rax)
incl 0x1c(%rbx)
movl %r13d, %ebp
jmp 0x1bfb
leal 0x1(%rdx), %eax
movl %eax, 0x70(%rbx)
movl %edx, -0x4(%rsi)
incl 0x18(%rbx)
movl %ecx, %ebp
jmp 0x1bfb
movl %eax, %ebp
movl %r13d, %eax
shlq $0x4, %rax
movl $0x0, 0x80(%rbx,%rax)
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq