// File: CMU-SAFARI[P]MQSim/src/ssd/TSU_Priority_OutOfOrder.cpp
// Function: SSD_Components::TSU_Priority_OutOfOrder::get_next_read_service_queue(NVM::FlashMemory::Flash_Chip*)
Flash_Transaction_Queue *TSU_Priority_OutOfOrder::get_next_read_service_queue(NVM::FlashMemory::Flash_Chip *chip)
{
    if (UserReadTRQueue[chip->ChannelID][chip->ChipID][IO_Flow_Priority_Class::URGENT].size() > 0)
    {
        return &UserReadTRQueue[chip->ChannelID][chip->ChipID][IO_Flow_Priority_Class::URGENT];
    }

    int numberOfTries = 0;
    while(numberOfTries < IO_Flow_Priority_Class::get_scheduling_weight(IO_Flow_Priority_Class::HIGH))
    {
        nextPriorityClassRead[chip->ChannelID][chip->ChipID] = IO_Flow_Priority_Class::to_priority((nextPriorityClassRead[chip->ChannelID][chip->ChipID] + 1) % IO_Flow_Priority_Class::NUMBER_OF_PRIORITY_LEVELS);
        if (nextPriorityClassRead[chip->ChannelID][chip->ChipID] == IO_Flow_Priority_Class::URGENT)
        {
            nextPriorityClassRead[chip->ChannelID][chip->ChipID] = IO_Flow_Priority_Class::HIGH;
        }
        if (nextPriorityClassRead[chip->ChannelID][chip->ChipID] == IO_Flow_Priority_Class::HIGH)
        {
            numberOfTries++;
            currentWeightRead[chip->ChannelID][chip->ChipID]--;
            if (currentWeightRead[chip->ChannelID][chip->ChipID] <= 0)
            {
                currentWeightRead[chip->ChannelID][chip->ChipID] = IO_Flow_Priority_Class::get_scheduling_weight(IO_Flow_Priority_Class::HIGH);
            }
        }
        if (IO_Flow_Priority_Class::get_scheduling_weight(nextPriorityClassRead[chip->ChannelID][chip->ChipID]) >= currentWeightRead[chip->ChannelID][chip->ChipID]
            && UserReadTRQueue[chip->ChannelID][chip->ChipID][nextPriorityClassRead[chip->ChannelID][chip->ChipID]].size() > 0)
        {
            return &UserReadTRQueue[chip->ChannelID][chip->ChipID][nextPriorityClassRead[chip->ChannelID][chip->ChipID]];
        }
    }

    return NULL;
}

// Assembly:
subq $0x38, %rsp
movq %rdi, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0xb0(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movq (%rax,%rcx,8), %rdi
addq $0x8, %rdi
callq 0x91c80
cmpq $0x0, %rax
jbe 0xa2fa4
movq 0x10(%rsp), %rax
movq 0xb0(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq %rax, 0x30(%rsp)
jmp 0xa322b
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
movl %eax, 0xc(%rsp)
movl $0x1, %edi
callq 0xa3e40
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jge 0xa3222
movq 0x10(%rsp), %rax
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movl (%rax,%rcx,4), %eax
addl $0x1, %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %edx, %edi
callq 0xa3ed0
movl %eax, %esi
movq 0x10(%rsp), %rax
movq 0xe8(%rax), %rcx
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rcx,%rdx,8), %rcx
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
movl %esi, (%rcx,%rdx,4)
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
cmpl $0x0, (%rax,%rcx,4)
jne 0xa306e
movq 0x10(%rsp), %rax
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movl $0x1, (%rax,%rcx,4)
movq 0x10(%rsp), %rax
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
cmpl $0x1, (%rax,%rcx,4)
jne 0xa311e
movq 0x10(%rsp), %rax
movl 0x1c(%rsp), %ecx
addl $0x1, %ecx
movl %ecx, 0x1c(%rsp)
movq 0xf8(%rax), %rcx
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rcx,%rdx,8), %rcx
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
movl (%rcx,%rdx,4), %esi
addl $-0x1, %esi
movl %esi, (%rcx,%rdx,4)
movq 0xf8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
cmpl $0x0, (%rax,%rcx,4)
jg 0xa311c
movl $0x1, %edi
callq 0xa3e40
movl %eax, %edx
movq 0x10(%rsp), %rax
movq 0xf8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movl %edx, (%rax,%rcx,4)
jmp 0xa311e
movq 0x10(%rsp), %rax
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movl (%rax,%rcx,4), %edi
callq 0xa3e40
movq 0x10(%rsp), %rcx
movq 0xf8(%rcx), %rcx
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rcx,%rdx,8), %rcx
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
cmpl (%rcx,%rdx,4), %eax
jl 0xa321d
movq 0x10(%rsp), %rax
movq 0xb0(%rax), %rcx
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rcx,%rdx,8), %rcx
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
movq (%rcx,%rdx,8), %rdi
movq 0xe8(%rax), %rax
movq 0x20(%rsp), %rcx
movl 0x2c(%rcx), %ecx
movq (%rax,%rcx,8), %rax
movq 0x20(%rsp), %rcx
movl 0x30(%rcx), %ecx
movl (%rax,%rcx,4), %eax
imulq $0x108, %rax, %rax      # imm = 0x108
addq %rax, %rdi
addq $0x8, %rdi
callq 0x91c80
cmpq $0x0, %rax
jbe 0xa321d
movq 0x10(%rsp), %rcx
movq 0xb0(%rcx), %rax
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rax,%rdx,8), %rax
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
movq (%rax,%rdx,8), %rax
movq 0xe8(%rcx), %rcx
movq 0x20(%rsp), %rdx
movl 0x2c(%rdx), %edx
movq (%rcx,%rdx,8), %rcx
movq 0x20(%rsp), %rdx
movl 0x30(%rdx), %edx
movl (%rcx,%rdx,4), %ecx
imulq $0x108, %rcx, %rcx      # imm = 0x108
addq %rcx, %rax
movq %rax, 0x30(%rsp)
jmp 0xa322b
jmp 0xa2fac
movq $0x0, 0x30(%rsp)
movq 0x30(%rsp), %rax
addq $0x38, %rsp
retq
nopw %cs:(%rax,%rax)