// File: /workspace/github_c_makefile_star2_O0/hobo0xcc[P]rve/src/cpu.c
// Function: DiskAccess
void DiskAccess(State *state) {
    // printf("Disk Access\n");
    uint64_t desc_addr = DescAddr(state);
    // printf("rve: desc: %lld\n", (int64_t)desc_addr);
    uint64_t avail_addr = DescAddr(state) + 8 * 16;
    // printf("rve: avail: %lld\n", (int64_t)avail_addr);
    uint64_t used_addr = DescAddr(state) + 4096;
    // printf("rve: used: %lld\n", (int64_t)used_addr);

    uint32_t queue_size = state->virtio->queue_num;
    uint16_t offset = Read16(state, avail_addr);
    uint16_t index = Read16(state, avail_addr + 2);
    uint64_t index_addr = avail_addr + 4 + (uint64_t)state->virtio->id * 2 /*desc_addr + VRING_DESC_SIZE * index*/;
    uint64_t head_index = Read16(state, index_addr) % queue_size;
    uint64_t desc_addr0 = desc_addr + VRING_DESC_SIZE * head_index;
    uint64_t addr0 = Read64(state, desc_addr0);
    uint16_t next0 = Read16(state, desc_addr0 + 14);
    uint64_t desc_addr1 = desc_addr + VRING_DESC_SIZE * next0;
    uint64_t addr1 = Read64(state, desc_addr1);
    uint32_t len1 = Read32(state, desc_addr1 + 8);
    uint16_t flags1 = Read16(state, desc_addr1 + 12);
    uint16_t next1 = Read64(state, desc_addr1 + 14);
    uint64_t desc_addr2 = desc_addr + VRING_DESC_SIZE * next1;
    uint64_t addr2 = Read64(state, desc_addr2);
    uint32_t len2 = Read32(state, desc_addr2 + 8);
    uint16_t flags2 = Read16(state, desc_addr2 + 12);

    uint64_t blk_sector = Read64(state, addr0 + 8);

    if ((flags1 & 2) == 0) {
        for (uint64_t i = 0; i < len1; i++) {
            uint8_t data = Read8(state, addr1 + i);
            WriteDisk(state, blk_sector * 512 + i, data);
        }
    } else {
        for (uint64_t i = 0; i < len1; i++) {
            uint8_t data = ReadDisk(state, blk_sector * 512 + i);
            Write8(state, addr1 + i, data);
            // printf("DiskRead disk_addr: %llx, addr: %llx, %c\n", blk_sector * 512 + i, addr1 + i, data);
        }
    }

    if (flags2 & 2) {
        Write8(state, addr2, 0);
    } else {
        Error("Third descriptor must be write mode");
    }

    uint64_t new_id = GetNewId(state) % queue_size;
    Write16(state, used_addr + 2, new_id % 8);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
callq 0x2fb0
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rdi
callq 0x2fb0
addq $0x80, %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rdi
callq 0x2fb0
addq $0x1000, %rax           # imm = 0x1000
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x8130(%rax), %rax
movl 0x10(%rax), %eax
movl %eax, -0x24(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x3040
movw %ax, -0x26(%rbp)
movq -0x8(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x2, %rsi
callq 0x3040
movw %ax, -0x28(%rbp)
movq -0x18(%rbp), %rax
addq $0x4, %rax
movq -0x8(%rbp), %rcx
movq 0x8130(%rcx), %rcx
movl 0x38(%rcx), %ecx
shlq %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x3040
movzwl %ax, %eax
xorl %edx, %edx
divl -0x24(%rbp)
movl %edx, %eax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x30a0
movq %rax, -0x48(%rbp)
movq -0x8(%rbp), %rdi
movq -0x40(%rbp), %rsi
addq $0xe, %rsi
callq 0x3040
movw %ax, -0x4a(%rbp)
movq -0x10(%rbp), %rax
movzwl -0x4a(%rbp), %ecx
shll $0x4, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
callq 0x30a0
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
addq $0x8, %rsi
callq 0x3100
movl %eax, -0x64(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
addq $0xc, %rsi
callq 0x3040
movw %ax, -0x66(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rsi
addq $0xe, %rsi
callq 0x30a0
movw %ax, -0x68(%rbp)
movq -0x10(%rbp), %rax
movzwl -0x68(%rbp), %ecx
shll $0x4, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rdi
movq -0x70(%rbp), %rsi
callq 0x30a0
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rdi
movq -0x70(%rbp), %rsi
addq $0x8, %rsi
callq 0x3100
movl %eax, -0x7c(%rbp)
movq -0x8(%rbp), %rdi
movq -0x70(%rbp), %rsi
addq $0xc, %rsi
callq 0x3040
movw %ax, -0x7e(%rbp)
movq -0x8(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq $0x8, %rsi
callq 0x30a0
movq %rax, -0x88(%rbp)
movzwl -0x66(%rbp), %eax
andl $0x2, %eax
cmpl $0x0, %eax
jne 0x2140
movq $0x0, -0x90(%rbp)
movq -0x90(%rbp), %rax
movl -0x64(%rbp), %ecx
cmpq %rcx, %rax
jae 0x213e
movq -0x8(%rbp), %rdi
movq -0x60(%rbp), %rsi
addq -0x90(%rbp), %rsi
callq 0x3160
movb %al, -0x91(%rbp)
movq -0x8(%rbp), %rdi
movq -0x88(%rbp), %rsi
shlq $0x9, %rsi
addq -0x90(%rbp), %rsi
movzbl -0x91(%rbp), %edx
callq 0x3010
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x90(%rbp)
jmp 0x20df
jmp 0x21ac
movq $0x0, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
movl -0x64(%rbp), %ecx
cmpq %rcx, %rax
jae 0x21aa
movq -0x8(%rbp), %rdi
movq -0x88(%rbp), %rsi
shlq $0x9, %rsi
addq -0xa0(%rbp), %rsi
callq 0x2fe0
movb %al, -0xa1(%rbp)
movq -0x8(%rbp), %rdi
movq -0x60(%rbp), %rsi
addq -0xa0(%rbp), %rsi
movzbl -0xa1(%rbp), %edx
callq 0x31c0
movq -0xa0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
jmp 0x214b
jmp 0x21ac
movzwl -0x7e(%rbp), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x21c9
movq -0x8(%rbp), %rdi
movq -0x78(%rbp), %rsi
xorl %edx, %edx
callq 0x31c0
jmp 0x21d7
leaq 0xd1c3(%rip), %rdi      # 0xf393
movb $0x0, %al
callq 0xd690
movq -0x8(%rbp), %rdi
callq 0x2f80
movl -0x24(%rbp), %ecx
xorl %edx, %edx
divq %rcx
movq %rdx, -0xb0(%rbp)
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rsi
addq $0x2, %rsi
movq -0xb0(%rbp), %rax
andq $0x7, %rax
movzwl %ax, %edx
callq 0x3220
addq $0xb0, %rsp
popq %rbp
retq
nopw (%rax,%rax)