// File: /workspace/github_c_makefile_star2_O0/TheDiamondProject[P]lib68/cpu/mmu.c
// Function: m68_mmu_page_alloc
void *m68_mmu_page_alloc(uint32_t address)
{
	union m68_mmu_page_entry *table = NULL;
	void *page = NULL;

	/* First determine the page table and the page that the address relates
	 * to. */
	uint32_t dir_idx = (address >> 22) & 0x3FF;
	uint32_t table_idx = (address >> 12) & 0x3FF;

	/* Now check if a table already exists. If not create it. To do this we need
	 * to request an allocation for the page and then ensure it is aligned to a
	 * 16 byte boundary. */
	if (!MMU_PAGE_DIR[dir_idx].field.present) {
		table = calloc(MMU_PAGE_TABLE_MAX_ENTRIES + 4, sizeof(union m68_mmu_page_entry));
		uintptr_t address = (uintptr_t)table;
		if (address & 0xF) {
			address = ((address + 0x10) & ~0xF);
			table = (void *)address;
		}

		MMU_PAGE_DIR[dir_idx].field.address = (address >> 2);
		MMU_PAGE_DIR[dir_idx].field.present = 1;
	} else {
		table = (void *)((uintptr_t)MMU_PAGE_DIR[dir_idx].field.address << 2);
	}

	/* Now check for the presence of the desired page in the table. If the page
	 * is not there then allocate it. */
	if (!table[table_idx].field.present) {
		page = calloc(0x1000, 1);
		uintptr_t address = (uintptr_t)page;
		if (address & 0xF) {
			address = ((address + 0x10) & ~0xF);
			page = (void *)address;
		}

		table[table_idx].field.address = (address >> 2);
		table[table_idx].field.present = 1;
	} else {
		page = (void *)((uintptr_t)table[table_idx].field.address << 2);
	}

	return page;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movl %edi, -0x4(%rbp)
movq $0x0, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movl -0x4(%rbp), %eax
shrl $0x16, %eax
andl $0x3ff, %eax            # imm = 0x3FF
movl %eax, -0x1c(%rbp)
movl -0x4(%rbp), %eax
shrl $0xc, %eax
andl $0x3ff, %eax            # imm = 0x3FF
movl %eax, -0x20(%rbp)
leaq 0x103672(%rip), %rax    # 0x109070
movq (%rax), %rax
movl -0x1c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x5aab
movl $0x404, %edi            # imm = 0x404
movl $0x8, %esi
callq 0x3050
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
andq $0xf, %rax
cmpq $0x0, %rax
je 0x5a57
movq -0x28(%rbp), %rax
addq $0x10, %rax
andq $-0x10, %rax
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x28(%rbp), %rsi
shrq $0x2, %rsi
leaq 0x10360a(%rip), %rax    # 0x109070
movq (%rax), %rax
movl -0x1c(%rbp), %ecx
movq (%rax,%rcx,8), %rdx
movabsq $0xfffffffffffffff, %rdi # imm = 0xFFFFFFFFFFFFFFF
andq %rdi, %rsi
shlq $0x4, %rsi
andq $0xf, %rdx
orq %rsi, %rdx
movq %rdx, (%rax,%rcx,8)
leaq 0x1035dd(%rip), %rax    # 0x109070
movq (%rax), %rax
movl -0x1c(%rbp), %ecx
movq (%rax,%rcx,8), %rdx
andq $-0x2, %rdx
orq $0x1, %rdx
movq %rdx, (%rax,%rcx,8)
jmp 0x5ac8
leaq 0x1035be(%rip), %rax    # 0x109070
movq (%rax), %rax
movl -0x1c(%rbp), %ecx
movq (%rax,%rcx,8), %rax
shrq $0x4, %rax
shlq $0x2, %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movq (%rax,%rcx,8), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x5b6a
movl $0x1000, %edi           # imm = 0x1000
movl $0x1, %esi
callq 0x3050
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
andq $0xf, %rax
cmpq $0x0, %rax
je 0x5b22
movq -0x30(%rbp), %rax
addq $0x10, %rax
andq $-0x10, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movq %rax, -0x18(%rbp)
movq -0x30(%rbp), %rsi
shrq $0x2, %rsi
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movq (%rax,%rcx,8), %rdx
movabsq $0xfffffffffffffff, %rdi # imm = 0xFFFFFFFFFFFFFFF
andq %rdi, %rsi
shlq $0x4, %rsi
andq $0xf, %rdx
orq %rsi, %rdx
movq %rdx, (%rax,%rcx,8)
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movq (%rax,%rcx,8), %rdx
andq $-0x2, %rdx
orq $0x1, %rdx
movq %rdx, (%rax,%rcx,8)
jmp 0x5b81
movq -0x10(%rbp), %rax
movl -0x20(%rbp), %ecx
movq (%rax,%rcx,8), %rax
shrq $0x4, %rax
shlq $0x2, %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax,%rax)