// File: /workspace/github_c_makefile_star2_O0/dlbeer[P]ufat/ufat_file.c
// Function: read_blocks
static int read_blocks(struct ufat_file *f, char *buf, ufat_size_t size)
{
	struct ufat *uf = f->uf;
	const struct ufat_bpb *bpb = &uf->bpb;
	const unsigned int log2_block_size = uf->dev->log2_block_size;
	const unsigned int blocks_per_cluster =
		1 << bpb->log2_blocks_per_cluster;
	const unsigned int block_offset =
		(f->cur_pos >> log2_block_size) & (blocks_per_cluster - 1);
	const unsigned int block_remainder =
		blocks_per_cluster - block_offset;
	ufat_block_t starting_block;
	unsigned int requested_blocks = size >> log2_block_size;
	int i;

	if (requested_blocks > block_remainder)
		requested_blocks = block_remainder;
	if (!requested_blocks)
		return 0;

	if (!UFAT_CLUSTER_IS_PTR(f->cur_cluster))
		return -UFAT_ERR_INVALID_CLUSTER;

	/* We're reading contiguous whole blocks, so we can bypass the
	 * cache and perform a single large read.
	 */
	starting_block = cluster_to_block(bpb, f->cur_cluster) + block_offset;
	i = ufat_cache_evict(uf, starting_block, requested_blocks);
	if (i < 0)
		return i;

	i = uf->dev->read(uf->dev, starting_block, requested_blocks, buf);
	if (i < 0)
		return -UFAT_ERR_IO;

	uf->stat.read++;
	uf->stat.read_blocks += requested_blocks;

	i = advance_ptr(f, requested_blocks << log2_block_size);
	if (i < 0)
		return i;

	return requested_blocks << log2_block_size;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x48(%rsp)
movq %rsi, 0x40(%rsp)
movl %edx, 0x3c(%rsp)
movq 0x48(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rax
addq $0x28, %rax
movq %rax, 0x28(%rsp)
movq 0x30(%rsp), %rax
movq (%rax), %rax
movl (%rax), %eax
movl %eax, 0x24(%rsp)
movq 0x28(%rsp), %rax
movl 0x4(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
movl %eax, 0x20(%rsp)
movq 0x48(%rsp), %rax
movl 0x24(%rax), %eax
movl 0x24(%rsp), %ecx
shrl %cl, %eax
movl 0x20(%rsp), %ecx
subl $0x1, %ecx
andl %ecx, %eax
movl %eax, 0x1c(%rsp)
movl 0x20(%rsp), %eax
subl 0x1c(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0x3c(%rsp), %eax
movl 0x24(%rsp), %ecx
shrl %cl, %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
cmpl 0x18(%rsp), %eax
jbe 0x5485
movl 0x18(%rsp), %eax
movl %eax, 0xc(%rsp)
cmpl $0x0, 0xc(%rsp)
jne 0x5499
movl $0x0, 0x54(%rsp)
jmp 0x5599
movq 0x48(%rsp), %rax
cmpl $0x2, 0x20(%rax)
jb 0x54b2
movq 0x48(%rsp), %rax
cmpl $0xffffff0, 0x20(%rax)  # imm = 0xFFFFFF0
jb 0x54bf
movl $0xfffffffb, 0x54(%rsp) # imm = 0xFFFFFFFB
jmp 0x5599
movq 0x28(%rsp), %rdi
movq 0x48(%rsp), %rax
movl 0x20(%rax), %esi
callq 0x5dc0
movl 0x1c(%rsp), %ecx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %rdi
movq 0x10(%rsp), %rsi
movl 0xc(%rsp), %eax
movl %eax, %edx
callq 0x22f0
movl %eax, 0x8(%rsp)
cmpl $0x0, 0x8(%rsp)
jge 0x550a
movl 0x8(%rsp), %eax
movl %eax, 0x54(%rsp)
jmp 0x5599
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq 0x8(%rax), %rax
movq 0x30(%rsp), %rcx
movq (%rcx), %rdi
movq 0x10(%rsp), %rsi
movl 0xc(%rsp), %ecx
movl %ecx, %edx
movq 0x40(%rsp), %rcx
callq *%rax
movl %eax, 0x8(%rsp)
cmpl $0x0, 0x8(%rsp)
jge 0x5545
movl $0xffffffff, 0x54(%rsp) # imm = 0xFFFFFFFF
jmp 0x5599
movq 0x30(%rsp), %rax
movl 0x8(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x8(%rax)
movl 0xc(%rsp), %ecx
movq 0x30(%rsp), %rax
addl 0x10(%rax), %ecx
movl %ecx, 0x10(%rax)
movq 0x48(%rsp), %rdi
movl 0xc(%rsp), %esi
movl 0x24(%rsp), %ecx
shll %cl, %esi
callq 0x5030
movl %eax, 0x8(%rsp)
cmpl $0x0, 0x8(%rsp)
jge 0x558b
movl 0x8(%rsp), %eax
movl %eax, 0x54(%rsp)
jmp 0x5599
movl 0xc(%rsp), %eax
movl 0x24(%rsp), %ecx
shll %cl, %eax
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)