// File: /workspace/github_c_makefile_star2_O0/j-hoppe[P]tu58fs/rt11.c
// Function: rt11_filesystem_calc_block_use
static int rt11_filesystem_calc_block_use(rt11_filesystem_t *_this, int test_data_size) {
	int i;
	int dir_max_seg_nr;
	int used_file_blocks;
	int available_blocks;

	if (_this->dir_entry_extra_bytes > 16)
		fatal("Extra bytes in directory %d is > 16 ... how much is allowed?", _this->dir_entry_extra_bytes);

	// 1) calc segments & blocks needed for existing files
	used_file_blocks = 0;
	for (i = 0; i < _this->file_count; i++) {
		// round file sizes up to blocks
		// prefix size and data size already sum'd up to file->block_count
		used_file_blocks += _this->file[i]->block_count;
	}
	if (test_data_size)
		used_file_blocks += NEEDED_BLOCKS(RT11_BLOCKSIZE, test_data_size);

	// total blocks available for dir and data
	// On disk supporting STd144 bad secotr info,
	// "available blocks" should not be calculated from total disk size,
	// but from usable blockcount of "rt11_radi".
	// Difficulties in case of enlarged images!
	available_blocks = _this->blockcount - _this->first_dir_blocknr; // boot, home, 2..5 used
	if (test_data_size)
		dir_max_seg_nr = rt11_dir_needed_segments(_this, _this->file_count + 1);
	else
		dir_max_seg_nr = rt11_dir_needed_segments(_this, _this->file_count);
	if (available_blocks < used_file_blocks + 2 * dir_max_seg_nr) {
		// files do not fit on volume
		if (!test_data_size)
			_this->free_blocks = 0; // can't be negative
		return error_set(ERROR_FILESYSTEM_OVERFLOW, "rt11_filesystem_calc_block_use");
	}
	if (test_data_size)
		return ERROR_OK;

	/* end of test mode */
	// now modify file system
	_this->dir_max_seg_nr = dir_max_seg_nr;
	_this->used_file_blocks = used_file_blocks;

	_this->free_blocks = available_blocks - _this->used_file_blocks - 2 * _this->dir_max_seg_nr;
	// now used_blocks,free_blocks, dir_total_seg_num valid.

	/* Plan use of remaining free_space
	 * how many files would be allocated in the remaining free space?
	 * derive from average file size, but allow 1.5 * as much
	 * Most critical test situations:
	 * All dir segments full, and only 2 block in file area left.
	 * assigned these blocks to 1 more file would need a new dir segment,
	 * which would need these 2 blocks too.
	 * If 3 blocks are left: 2 can be used for additional dir segmetn,
	 * and 1 for new file.
	 */
	if (_this->file_count == 0) {
		// if disk empty: start with only 1 segment
		_this->dir_max_seg_nr = 1;
		_this->dir_total_seg_num = 1;
	} else {
		// planning params have prefix "_"
		int avg_file_blocks; // average filesize in blocks
		int _new_file_count; // planned count of additional files
		int _used_file_blocks; // planned block requirement for all files (existing + planned)
		int _dir_total_seg_num; // planned dir segment requirement for all files (existing + planned)
		avg_file_blocks = _this->used_file_blocks / _this->file_count;
		if (avg_file_blocks < 1)
			avg_file_blocks = 1;
		// 1st estimate for possible new files.
		// Assume they have average size.
		// too big, since additional dir segments reduce free space
		_new_file_count = _this->free_blocks / avg_file_blocks + 1;
		// reduce amount of planned files, until files+dir fit on disk
		do {
			_new_file_count--;
			_used_file_blocks = _this->used_file_blocks + _new_file_count * avg_file_blocks;
			// plan for 50% more file count
			_dir_total_seg_num = rt11_dir_needed_segments(_this,
					_this->file_count + (_new_file_count * 3) / 2);
		} while (_new_file_count
				&& available_blocks < _used_file_blocks + 2 * _dir_total_seg_num);
		// solution found: save
		if (_dir_total_seg_num > 31)
			_dir_total_seg_num = 31;
		_this->dir_total_seg_num = _dir_total_seg_num;
	}
	// calculate free blocks again
	assert(available_blocks >= _this->used_file_blocks + 2 * _this->dir_total_seg_num);
	_this->free_blocks = available_blocks - _this->used_file_blocks
			- 2 * _this->dir_total_seg_num;

	return ERROR_OK;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rax
movzwl 0x68(%rax), %eax
cmpl $0x10, %eax
jle 0x156b2
movq -0x10(%rbp), %rax
movzwl 0x68(%rax), %esi
leaq 0x850b(%rip), %rdi      # 0x1dbb6
movb $0x0, %al
callq 0xd140
movl $0x0, -0x20(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
movq -0x10(%rbp), %rcx
cmpl 0x8c(%rcx), %eax
jge 0x156f4
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
movq 0x90(%rax,%rcx,8), %rax
movzwl 0x7c(%rax), %eax
addl -0x20(%rbp), %eax
movl %eax, -0x20(%rbp)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x156c0
cmpl $0x0, -0x14(%rbp)
je 0x15713
movl -0x14(%rbp), %eax
addl $0x200, %eax            # imm = 0x200
subl $0x1, %eax
movl $0x200, %ecx            # imm = 0x200
cltd
idivl %ecx
addl -0x20(%rbp), %eax
movl %eax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movl 0x6c(%rax), %eax
movq -0x10(%rbp), %rcx
movzwl 0x34(%rcx), %ecx
subl %ecx, %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x15748
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8c(%rax), %esi
addl $0x1, %esi
callq 0x17000
movl %eax, -0x1c(%rbp)
jmp 0x1575e
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8c(%rax), %esi
callq 0x17000
movl %eax, -0x1c(%rbp)
movl -0x24(%rbp), %eax
movl -0x20(%rbp), %ecx
movl -0x1c(%rbp), %edx
shll %edx
addl %edx, %ecx
cmpl %ecx, %eax
jge 0x1579d
cmpl $0x0, -0x14(%rbp)
jne 0x15782
movq -0x10(%rbp), %rax
movw $0x0, 0x1fd2(%rax)
movl $0xfffffffe, %edi       # imm = 0xFFFFFFFE
leaq 0x8465(%rip), %rsi      # 0x1dbf3
movb $0x0, %al
callq 0xcd70
movl %eax, -0x4(%rbp)
jmp 0x1594f
cmpl $0x0, -0x14(%rbp)
je 0x157af
movl $0x0, -0x4(%rbp)
jmp 0x1594f
movl -0x1c(%rbp), %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x66(%rax)
movl -0x20(%rbp), %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x1fd0(%rax)
movl -0x24(%rbp), %eax
movq -0x10(%rbp), %rcx
movzwl 0x1fd0(%rcx), %ecx
subl %ecx, %eax
movq -0x10(%rbp), %rcx
movzwl 0x66(%rcx), %ecx
shll %ecx
subl %ecx, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x1fd2(%rax)
movq -0x10(%rbp), %rax
cmpl $0x0, 0x8c(%rax)
jne 0x1581e
movq -0x10(%rbp), %rax
movw $0x1, 0x66(%rax)
movq -0x10(%rbp), %rax
movw $0x1, 0x64(%rax)
jmp 0x158df
movq -0x10(%rbp), %rax
movzwl 0x1fd0(%rax), %eax
movq -0x10(%rbp), %rcx
cltd
idivl 0x8c(%rcx)
movl %eax, -0x28(%rbp)
cmpl $0x1, -0x28(%rbp)
jge 0x15844
movl $0x1, -0x28(%rbp)
movq -0x10(%rbp), %rax
movzwl 0x1fd2(%rax), %eax
cltd
idivl -0x28(%rbp)
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movzwl 0x1fd0(%rax), %eax
movl -0x2c(%rbp), %ecx
imull -0x28(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movq -0x10(%rbp), %rax
movl 0x8c(%rax), %esi
imull $0x3, -0x2c(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
addl %eax, %esi
callq 0x17000
movl %eax, -0x34(%rbp)
xorl %eax, %eax
cmpl $0x0, -0x2c(%rbp)
movb %al, -0x35(%rbp)
je 0x158bd
movl -0x24(%rbp), %eax
movl -0x30(%rbp), %ecx
movl -0x34(%rbp), %edx
shll %edx
addl %edx, %ecx
cmpl %ecx, %eax
setl %al
movb %al, -0x35(%rbp)
movb -0x35(%rbp), %al
testb $0x1, %al
jne 0x15859
cmpl $0x1f, -0x34(%rbp)
jle 0x158d1
movl $0x1f, -0x34(%rbp)
movl -0x34(%rbp), %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x64(%rax)
movl -0x24(%rbp), %eax
movq -0x10(%rbp), %rcx
movzwl 0x1fd0(%rcx), %ecx
movq -0x10(%rbp), %rdx
movzwl 0x64(%rdx), %edx
shll %edx
addl %edx, %ecx
cmpl %ecx, %eax
jl 0x158ff
jmp 0x1591e
leaq 0x830c(%rip), %rdi      # 0x1dc12
leaq 0x7d2b(%rip), %rsi      # 0x1d638
movl $0x1c9, %edx            # imm = 0x1C9
leaq 0x8344(%rip), %rcx      # 0x1dc5d
callq 0x3200
movl -0x24(%rbp), %eax
movq -0x10(%rbp), %rcx
movzwl 0x1fd0(%rcx), %ecx
subl %ecx, %eax
movq -0x10(%rbp), %rcx
movzwl 0x64(%rcx), %ecx
shll %ecx
subl %ecx, %eax
movw %ax, %cx
movq -0x10(%rbp), %rax
movw %cx, 0x1fd2(%rax)
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)