// File: narges64[P]SIMBA/garbage_collection.cpp
// Function: RGA_algorithm(ssd_info*, local*)
STATE RGA_algorithm(ssd_info * ssd, local * location){
	unsigned int window_size = 200; // FIXME
	unsigned int total_size = ssd->parameter->block_plane;

	int * blocks = new int[total_size];
	for (int i = 0; i < total_size; i++){
		blocks[i] = i;
	}

	int active_block = get_active_block(ssd, location);
	int cold_active_block = get_cold_active_block(ssd, location); 
	plane_info * p = ssd->channel_head[location->channel]->lun_head[location->lun]->plane_head[location->plane];

	blocks[active_block] = blocks[total_size - 1];
	total_size--;
	blocks[cold_active_block] = blocks[total_size -1]; 
	total_size--; 

	for (int i = 0; i < window_size; i++){
		int j = rand() % (total_size - i);
		while ((p->blk_head[j]->free_page_num >0) || (j ==active_block) || (j == cold_active_block)) {
			j = rand() % (total_size - i); 
		}
		if (j != 0){
			int temp = blocks[i];
			blocks[i] = blocks[i+j];
			blocks[i + j] = temp;
		}
	}

	int block = -1;
	int max_invalid = 0; 
	for (int i = 0; i < window_size; i++){
		int temp = blocks[i]; 
		if (temp == active_block || temp == cold_active_block) continue; 
		if (p->blk_head[temp]->free_page_num > 0) continue; 
		if (p->blk_head[temp]->invalid_page_num > max_invalid) {
			block = temp; 
			max_invalid = p->blk_head[temp]->invalid_page_num; 
		}
		
	}
	if (block == -1) 
			greedy_algorithm(ssd, location); 
	
	location->block = block;
	delete blocks;

	return SUCCESS;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0xc8, -0x14(%rbp)
movq -0x8(%rbp), %rax
movq 0x58(%rax), %rax
movl 0x230(%rax), %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %eax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2040
movq %rax, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x18(%rbp), %eax
jae 0xadc8
movl -0x24(%rbp), %edx
movq -0x20(%rbp), %rax
movslq -0x24(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0xada7
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x86c0
movl %eax, -0x28(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x88d0
movl %eax, -0x2c(%rbp)
movq -0x8(%rbp), %rax
movq 0x90(%rax), %rax
movq -0x10(%rbp), %rcx
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rax
movq 0x50(%rax), %rax
movq -0x10(%rbp), %rcx
movslq 0x4(%rcx), %rcx
movq (%rax,%rcx,8), %rax
movq (%rax), %rax
movq -0x10(%rbp), %rcx
movslq 0x8(%rcx), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movl -0x18(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %edx
movq -0x20(%rbp), %rax
movslq -0x28(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x18(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x18(%rbp)
movq -0x20(%rbp), %rax
movl -0x18(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movl (%rax,%rcx,4), %edx
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x18(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x18(%rbp)
movl $0x0, -0x3c(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x14(%rbp), %eax
jae 0xaf2f
callq 0x2090
movl -0x18(%rbp), %ecx
subl -0x3c(%rbp), %ecx
xorl %edx, %edx
divl %ecx
movl %edx, -0x40(%rbp)
movq -0x38(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x40(%rbp), %rcx
movq (%rax,%rcx,8), %rcx
movb $0x1, %al
cmpl $0x0, 0x4(%rcx)
movb %al, -0x55(%rbp)
jg 0xaec0
movl -0x40(%rbp), %ecx
movb $0x1, %al
cmpl -0x28(%rbp), %ecx
movb %al, -0x55(%rbp)
je 0xaec0
movl -0x40(%rbp), %eax
cmpl -0x2c(%rbp), %eax
sete %al
movb %al, -0x55(%rbp)
movb -0x55(%rbp), %al
testb $0x1, %al
jne 0xaec9
jmp 0xaedd
callq 0x2090
movl -0x18(%rbp), %ecx
subl -0x3c(%rbp), %ecx
xorl %edx, %edx
divl %ecx
movl %edx, -0x40(%rbp)
jmp 0xae8c
cmpl $0x0, -0x40(%rbp)
je 0xaf1f
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x44(%rbp)
movq -0x20(%rbp), %rax
movl -0x3c(%rbp), %ecx
addl -0x40(%rbp), %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
movq -0x20(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x44(%rbp), %edx
movq -0x20(%rbp), %rax
movl -0x3c(%rbp), %ecx
addl -0x40(%rbp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
jmp 0xaf21
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0xae6e
movl $0xffffffff, -0x48(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl -0x14(%rbp), %eax
jae 0xafc8
movq -0x20(%rbp), %rax
movslq -0x50(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %eax
cmpl -0x28(%rbp), %eax
je 0xaf6a
movl -0x54(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jne 0xaf6c
jmp 0xafba
movq -0x38(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpl $0x0, 0x4(%rax)
jle 0xaf84
jmp 0xafba
movq -0x38(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x8(%rax), %eax
cmpl -0x4c(%rbp), %eax
jle 0xafb8
movl -0x54(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x38(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x54(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl 0x8(%rax), %eax
movl %eax, -0x4c(%rbp)
jmp 0xafba
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0xaf44
cmpl $-0x1, -0x48(%rbp)
jne 0xafdb
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0xab60
movl -0x48(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x20(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, %rax
je 0xb001
movq -0x60(%rbp), %rdi
movl $0x4, %esi
callq 0x2140
movl $0x1, %eax
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)