// File: sangwoojun[P]rv32emulator/emulator.cpp
// Function: execute(unsigned char*, instr*, label_loc*, int, bool)
void execute(uint8_t* mem, instr* imem, label_loc* labels, int label_count, bool start_immediate) {
	uint32_t rf[32];
	uint32_t rf_mirror[32];
	uint32_t pc = 0;
	uint32_t inst_cnt = 0;
	for ( int i = 0; i < 32; i++ ) {
		rf[i] = 0;
		rf_mirror[i] = 0;
	}

	bool stepping = !start_immediate;
	int stepcnt = 0;
	char keybuf[128];
	char* kbp = keybuf;


	bool dexit = false;
	while(!dexit) {
		uint32_t iid = pc/4;
		instr i = imem[iid];
		inst_cnt ++;

		if ( stepping || i.breakpoint ) {
			if ( stepcnt > 0 ) {
				stepcnt -= 1;
			} 

			if ( stepcnt == 0 || i.breakpoint ) {
				stepping = true;
				printf( "\n" );
				if ( i.psrc ) printf( "Next: %s\n", i.psrc );
				while (true) {
					printf( "[inst: %6d pc: %6d, src line %4d]\n", inst_cnt, pc, i.orig_line );

					std::string linebuf;
					fflush(stdout);
					linenoise::Readline(">>", linebuf);
					memcpy(keybuf, linebuf.c_str(), 128);
					linenoise::AddHistory(linebuf.c_str());
					//while ((kbp = linenoise?::Readline(">>")) == NULL);
					//fgets(keybuf, 128, stdin);


					for ( int i = 0; i < strlen(keybuf); i++ ) if (keybuf[i] == '\n') keybuf[i] = '\0';

					if ( keybuf[0] == 'q' ) {
						printf( "Quit command input! Exiting...\n" );
						exit(0);
					}
					if ( keybuf[0] == 'c' ) {
						stepping = false;
						break;
					}
					if ( strlen(keybuf) == 0 ) {
						break;
					}
					if ( keybuf[0] == 's' ) {
						stepcnt = parse_imm(keybuf+1, 16, 0, false);
						break;
					}
					if ( keybuf[0] == 'b' ) { // todo breakpoint!
						uint32_t break_line = parse_imm(keybuf+1, 16, 0, false);
						if ( strlen(keybuf+1) == 0 ) {
							for ( int i = 0; i < DATA_OFFSET/4; i++ ) {
								if ( imem[i].breakpoint ) printf( "Break at line %d: %s\n", imem[i].orig_line, imem[i].psrc );
							}
						} else {
							for ( int i = 0; i < DATA_OFFSET/4; i++ ) {
								if ( imem[i].orig_line >= break_line ) {
									printf( "Break point added to line %d\n", break_line );
									imem[i].breakpoint = true;
									break;
								}
							}
						}
					}
					if ( keybuf[0] == 'B' ) { // breakpoint remove
						uint32_t break_line = parse_imm(keybuf+1, 16, 0, false);
						for ( int i = 0; i < DATA_OFFSET/4; i++ ) {
							if ( imem[i].orig_line == break_line && imem[i].breakpoint ) {
								printf( "Break point removed from line %d\n", break_line );
								imem[i].breakpoint = false;
								break;
							}
						}
					}
					if ( keybuf[0] == 'r' ) {
						int reg = parse_reg(keybuf+1, 0, false);
						if ( reg >= 0 ) printf( "rf[%2d] = 0x%x\n", reg, rf[reg] );
						if ( reg < 0 ) print_regfile(rf);
					}
					if ( keybuf[0] == 'm' ) {
						uint32_t addr = parse_imm(keybuf+1, 31, 0, false); // just for simplicity
						int cnt = 1;
						char* ftok = strtok(keybuf, " \t\r\n");
						ftok = strtok(NULL, " \t\r\n");
						if ( ftok ) {
							cnt = parse_imm(ftok, 16, 0, false);
						}

						for ( int w = 0; w < cnt; w++ ) {
							printf( "0x%04x: ", addr+(w*4) );
							for ( int i = 0; i < 4; i++ ) {
								printf( "%02x ", mem[addr+(w*4)+i] );
							}
							printf( "\n" );
						}
					}
					if ( keybuf[0] == 'l' ) {
						printf( "Listing compiled isntructions\n" );
						printf( " srcline : Compiled instruction\n" );
						for ( int i = 0; i < DATA_OFFSET/4; i++ ) {
							instr* ii = &imem[i];
							if ( ii->orig_line >= 0 && ii->psrc ) {
								printf( "%9d: %s\n", ii->orig_line, ii->psrc );
							}
						}
					}
				}
			}
		}
		
		int pc_next = pc + 4;
		switch (i.op) {
			case ADD: rf[i.a1.reg] = rf[i.a2.reg] + rf[i.a3.reg]; break;
			case SUB: rf[i.a1.reg] = rf[i.a2.reg] - rf[i.a3.reg]; break;
			case SLT: rf[i.a1.reg] = (*(int32_t*)&rf[i.a2.reg]) < (*(int32_t*)&rf[i.a3.reg]) ? 1 : 0; break;
			case SLTU: rf[i.a1.reg] = rf[i.a2.reg] + rf[i.a3.reg]; break;
			case AND: rf[i.a1.reg] = rf[i.a2.reg] & rf[i.a3.reg]; break;
			case OR: rf[i.a1.reg] = rf[i.a2.reg] | rf[i.a3.reg]; break;
			case XOR: rf[i.a1.reg] = rf[i.a2.reg] ^ rf[i.a3.reg]; break;
			case SLL: rf[i.a1.reg] = rf[i.a2.reg] << rf[i.a3.reg]; break;
			case SRL: rf[i.a1.reg] = rf[i.a2.reg] >> rf[i.a3.reg]; break;
			case SRA: rf[i.a1.reg] = (*(int32_t*)&rf[i.a2.reg]) >> rf[i.a3.reg]; break;


			case ADDI: rf[i.a1.reg] = rf[i.a2.reg] + i.a3.imm; break;
			case SLTI: rf[i.a1.reg] = (*(int32_t*)&rf[i.a2.reg]) < (*(int32_t*)&(i.a3.imm)) ? 1 : 0; break;
			case SLTIU: rf[i.a1.reg] = rf[i.a2.reg] < i.a3.imm ? 1 : 0; break;
			case ANDI: rf[i.a1.reg] = rf[i.a2.reg] & i.a3.imm; break;
			case ORI: rf[i.a1.reg] = rf[i.a2.reg] | i.a3.imm; break;
			case XORI: rf[i.a1.reg] = rf[i.a2.reg] ^ i.a3.imm; break;
			case SLLI: rf[i.a1.reg] = rf[i.a2.reg] << i.a3.imm; break;
			case SRLI: rf[i.a1.reg] = rf[i.a2.reg] >> i.a3.imm; break;
			case SRAI: rf[i.a1.reg] = (*(int32_t*)&rf[i.a2.reg]) >> i.a3.imm; break;

			case LB:
			case LBU: 
			case LH:
			case LHU:
			case LW: rf[i.a1.reg] = mem_read(mem, rf[i.a2.reg]+i.a3.imm, i.op); break;
			
			case SB: 
			case SH: 
			case SW: mem_write(mem, rf[i.a2.reg]+i.a3.imm, rf[i.a1.reg], i.op); break;
			/*

			case SB: mem[rf[i.a2.reg]+i.a3.imm] = *(uint8_t*)&(rf[i.a1.reg]); break;
			case SH: *(uint16_t*)&(mem[rf[i.a2.reg]+i.a3.imm]) = *(uint16_t*)&(rf[i.a1.reg]); break;
			case SW: 
				*(uint32_t*)&(mem[rf[i.a2.reg]+i.a3.imm]) = rf[i.a1.reg]; 
				//printf( "Writing %x to addr %x\n", rf[i.a1.reg], rf[i.a2.reg]+i.a3.imm );
			break;
			*/

			case BEQ: if ( rf[i.a1.reg] == rf[i.a2.reg] ) pc_next = i.a3.imm; break;
			case BGE: if ( *(int32_t*)&rf[i.a1.reg] >= *(int32_t*)&rf[i.a2.reg] ) pc_next = i.a3.imm; break;
			case BGEU: if ( rf[i.a1.reg] >= rf[i.a2.reg] ) pc_next = i.a3.imm; 
				break;
			case BLT: if ( *(int32_t*)&rf[i.a1.reg] < *(int32_t*)&rf[i.a2.reg] ) pc_next = i.a3.imm; break;
			case BLTU: if ( rf[i.a1.reg] < rf[i.a2.reg] ) pc_next = i.a3.imm; break;
			case BNE: if ( rf[i.a1.reg] != rf[i.a2.reg] ) pc_next = i.a3.imm; break;

			case JAL:
				rf[i.a1.reg] = pc + 4;
				pc_next = i.a2.imm;
				//printf( "jal %d %x\n", pc+4, pc_next );
				break;
			case JALR:
				rf[i.a1.reg] = pc + 4;
				pc_next = rf[i.a2.reg] + i.a3.imm;
				//printf( "jalr %d %d(%d)\n", i.a1.reg, i.a3.imm, i.a2.reg );
				break;
			case AUIPC:
				rf[i.a1.reg] = pc + (i.a2.imm<<12);
				//printf( "auipc %x \n", rf[i.a1.reg] );
				break;
			case LUI:
				rf[i.a1.reg] = (i.a2.imm<<12);
				//printf( "lui %x \n", rf[i.a1.reg] );
				break;
			
			case HCF:
				printf( "\n\n----------\n\n" );
				printf( "Reached Halt and Catch Fire instruction!\n" );
				printf( "inst: %6d pc: %6d src line: %d\n", inst_cnt, pc, i.orig_line );
				print_regfile(rf);
				printf( "Cache read %d/%d Cache write %d/%d\n", cache_read_hits, mem_read_reqs, cache_write_hits, mem_write_reqs );
				printf( "Cache flush words: %d\n", mem_flush_words);
				dexit = true;
				break;
			case UNIMPL:
			default:
				printf( "Reached an unimplemented instruction!\n" );
				if ( i.psrc ) printf( "Instruction: %s\n", i.psrc );
				printf( "inst: %6d pc: %6d src line: %d\n", inst_cnt, pc, i.orig_line );
				print_regfile(rf);
				dexit = true;
				break;
		}
		pc = pc_next % MEM_BYTES;
		rf[0] = 0;// cleaner way to do this?
		if ( stepping ) {
			for ( int i = 0; i < 32; i++ ) {
				if ( rf[i] != rf_mirror[i] ) printf( ">> rf[x%02d] %x -> %x\n", i, rf_mirror[i], rf[i] );
				rf_mirror[i] = rf[i];
			}
		}

		//printf( "reg dst %d -> %x %d\n", i.a1.reg, rf[i.a1.reg], rf[i.a1.reg] );

		fflush(stdout);
		
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x320, %rsp            # imm = 0x320
movb %r8b, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
andb $0x1, %al
movb %al, -0x1d(%rbp)
movl $0x0, -0x124(%rbp)
movl $0x0, -0x128(%rbp)
movl $0x0, -0x12c(%rbp)
cmpl $0x20, -0x12c(%rbp)
jge 0x58be
movslq -0x12c(%rbp), %rax
movl $0x0, -0xa0(%rbp,%rax,4)
movslq -0x12c(%rbp), %rax
movl $0x0, -0x120(%rbp,%rax,4)
movl -0x12c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x12c(%rbp)
jmp 0x5880
movb -0x1d(%rbp), %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x12d(%rbp)
movl $0x0, -0x134(%rbp)
leaq -0x1c0(%rbp), %rax
movq %rax, -0x1c8(%rbp)
movb $0x0, -0x1c9(%rbp)
movb -0x1c9(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x58fb
jmp 0x685d
movl -0x124(%rbp), %eax
shrl $0x2, %eax
movl %eax, -0x1d0(%rbp)
movq -0x10(%rbp), %rsi
movl -0x1d0(%rbp), %eax
imulq $0x98, %rax, %rax
addq %rax, %rsi
leaq -0x268(%rbp), %rdi
movl $0x98, %edx
callq 0x2190
movl -0x128(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x128(%rbp)
testb $0x1, -0x12d(%rbp)
jne 0x5954
testb $0x1, -0x1d4(%rbp)
je 0x60c9
cmpl $0x0, -0x134(%rbp)
jle 0x596c
movl -0x134(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x134(%rbp)
cmpl $0x0, -0x134(%rbp)
je 0x5982
testb $0x1, -0x1d4(%rbp)
je 0x60c7
movb $0x1, -0x12d(%rbp)
leaq 0x5e82(%rip), %rdi      # 0xb812
movb $0x0, %al
callq 0x2040
cmpq $0x0, -0x1e0(%rbp)
je 0x59b6
movq -0x1e0(%rbp), %rsi
leaq 0x5d48(%rip), %rdi      # 0xb6f7
movb $0x0, %al
callq 0x2040
jmp 0x59b8
movl -0x128(%rbp), %esi
movl -0x124(%rbp), %edx
movl -0x1d8(%rbp), %ecx
leaq 0x5d30(%rip), %rdi      # 0xb701
xorl %eax, %eax
callq 0x2040
leaq -0x288(%rbp), %rdi
callq 0x22e0
movq 0x95cd(%rip), %rax      # 0xefb8
movq (%rax), %rdi
callq 0x2230
jmp 0x59f5
leaq 0x5d28(%rip), %rdi      # 0xb724
leaq -0x288(%rbp), %rsi
callq 0x6ef0
jmp 0x5a0a
leaq -0x288(%rbp), %rdi
movq %rdi, -0x2f8(%rbp)
callq 0x20e0
movq -0x2f8(%rbp), %rdi
movq %rax, -0x2f0(%rbp)
movups 0x70(%rax), %xmm0
movaps %xmm0, -0x150(%rbp)
movups 0x60(%rax), %xmm0
movaps %xmm0, -0x160(%rbp)
movups 0x50(%rax), %xmm0
movaps %xmm0, -0x170(%rbp)
movups 0x40(%rax), %xmm0
movaps %xmm0, -0x180(%rbp)
movups (%rax), %xmm0
movups 0x10(%rax), %xmm1
movups 0x20(%rax), %xmm2
movups 0x30(%rax), %xmm3
movaps %xmm3, -0x190(%rbp)
movaps %xmm2, -0x1a0(%rbp)
movaps %xmm1, -0x1b0(%rbp)
movaps %xmm0, -0x1c0(%rbp)
callq 0x20e0
movq %rax, %rdi
callq 0x6f60
jmp 0x5a91
movl $0x0, -0x298(%rbp)
movslq -0x298(%rbp), %rax
movq %rax, -0x300(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x2100
movq %rax, %rcx
movq -0x300(%rbp), %rax
cmpq %rcx, %rax
jae 0x5b22
movslq -0x298(%rbp), %rax
movsbl -0x1c0(%rbp,%rax), %eax
cmpl $0xa, %eax
jne 0x5b0c
movslq -0x298(%rbp), %rax
movb $0x0, -0x1c0(%rbp,%rax)
jmp 0x5b0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x290(%rbp)
movl %eax, -0x294(%rbp)
leaq -0x288(%rbp), %rdi
callq 0x2160
jmp 0x6866
jmp 0x5b0e
movl -0x298(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x298(%rbp)
jmp 0x5a9b
movsbl -0x1c0(%rbp), %eax
cmpl $0x71, %eax
jne 0x5b45
leaq 0x5bf2(%rip), %rdi      # 0xb727
xorl %eax, %eax
callq 0x2040
jmp 0x5b3e
xorl %edi, %edi
callq 0x2250
movsbl -0x1c0(%rbp), %eax
cmpl $0x63, %eax
jne 0x5b67
movb $0x0, -0x12d(%rbp)
movl $0x8, -0x29c(%rbp)
jmp 0x60a6
leaq -0x1c0(%rbp), %rdi
callq 0x2100
cmpq $0x0, %rax
jne 0x5b88
movl $0x8, -0x29c(%rbp)
jmp 0x60a6
movsbl -0x1c0(%rbp), %eax
cmpl $0x73, %eax
jne 0x5bcc
leaq -0x1bf(%rbp), %rdi
movl $0x10, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x3720
movl %eax, -0x304(%rbp)
jmp 0x5bb1
movl -0x304(%rbp), %eax
movl %eax, -0x134(%rbp)
movl $0x8, -0x29c(%rbp)
jmp 0x60a6
movsbl -0x1c0(%rbp), %eax
cmpl $0x62, %eax
jne 0x5d1e
leaq -0x1bf(%rbp), %rdi
movl $0x10, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x3720
movl %eax, -0x308(%rbp)
jmp 0x5bf9
movl -0x308(%rbp), %eax
movl %eax, -0x2a0(%rbp)
leaq -0x1c0(%rbp), %rdi
addq $0x1, %rdi
callq 0x2100
cmpq $0x0, %rax
jne 0x5c9a
movl $0x0, -0x2a4(%rbp)
cmpl $0x2000, -0x2a4(%rbp)   # imm = 0x2000
jge 0x5c95
movq -0x10(%rbp), %rax
movslq -0x2a4(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
testb $0x1, 0x94(%rax)
je 0x5c82
movq -0x10(%rbp), %rax
movslq -0x2a4(%rbp), %rcx
imulq $0x98, %rcx, %rcx
movl 0x90(%rax,%rcx), %esi
movq 0x88(%rax,%rcx), %rdx
leaq 0x5ad0(%rip), %rdi      # 0xb747
xorl %eax, %eax
callq 0x2040
jmp 0x5c80
jmp 0x5c82
jmp 0x5c84
movl -0x2a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2a4(%rbp)
jmp 0x5c25
jmp 0x5d1c
movl $0x0, -0x2a8(%rbp)
cmpl $0x2000, -0x2a8(%rbp)   # imm = 0x2000
jge 0x5d1a
movq -0x10(%rbp), %rax
movslq -0x2a8(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movl 0x90(%rax), %eax
cmpl -0x2a0(%rbp), %eax
jb 0x5d07
movl -0x2a0(%rbp), %esi
leaq 0x5a7d(%rip), %rdi      # 0xb75d
xorl %eax, %eax
callq 0x2040
jmp 0x5ce9
movq -0x10(%rbp), %rax
movslq -0x2a8(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movb $0x1, 0x94(%rax)
jmp 0x5d1a
jmp 0x5d09
movl -0x2a8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2a8(%rbp)
jmp 0x5ca4
jmp 0x5d1c
jmp 0x5d1e
movsbl -0x1c0(%rbp), %eax
cmpl $0x42, %eax
jne 0x5dfe
leaq -0x1bf(%rbp), %rdi
movl $0x10, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x3720
movl %eax, -0x30c(%rbp)
jmp 0x5d4b
movl -0x30c(%rbp), %eax
movl %eax, -0x2ac(%rbp)
movl $0x0, -0x2b0(%rbp)
cmpl $0x2000, -0x2b0(%rbp)   # imm = 0x2000
jge 0x5dfc
movq -0x10(%rbp), %rax
movslq -0x2b0(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movl 0x90(%rax), %eax
cmpl -0x2ac(%rbp), %eax
jne 0x5de6
movq -0x10(%rbp), %rax
movslq -0x2b0(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
testb $0x1, 0x94(%rax)
je 0x5de6
movl -0x2ac(%rbp), %esi
leaq 0x59bc(%rip), %rdi      # 0xb77b
xorl %eax, %eax
callq 0x2040
jmp 0x5dc8
movq -0x10(%rbp), %rax
movslq -0x2b0(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movb $0x0, 0x94(%rax)
jmp 0x5dfc
jmp 0x5de8
movl -0x2b0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2b0(%rbp)
jmp 0x5d61
jmp 0x5dfe
movsbl -0x1c0(%rbp), %eax
cmpl $0x72, %eax
jne 0x5e74
leaq -0x1bf(%rbp), %rdi
xorl %edx, %edx
movl %edx, %esi
callq 0x3250
movl %eax, -0x310(%rbp)
jmp 0x5e22
movl -0x310(%rbp), %eax
movl %eax, -0x2b4(%rbp)
cmpl $0x0, -0x2b4(%rbp)
jl 0x5e59
movslq -0x2b4(%rbp), %rax
movl %eax, %esi
movl -0xa0(%rbp,%rax,4), %edx
leaq 0x594f(%rip), %rdi      # 0xb79d
xorl %eax, %eax
callq 0x2040
jmp 0x5e57
jmp 0x5e59
cmpl $0x0, -0x2b4(%rbp)
jge 0x5e72
leaq -0xa0(%rbp), %rdi
callq 0x2cc0
jmp 0x5e70
jmp 0x5e72
jmp 0x5e74
movsbl -0x1c0(%rbp), %eax
cmpl $0x6d, %eax
jne 0x5fdb
leaq -0x1bf(%rbp), %rdi
movl $0x1f, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x3720
movl %eax, -0x314(%rbp)
jmp 0x5ea1
movl -0x314(%rbp), %eax
movl %eax, -0x2b8(%rbp)
movl $0x1, -0x2bc(%rbp)
leaq -0x1c0(%rbp), %rdi
leaq 0x5691(%rip), %rsi      # 0xb556
callq 0x2390
movq %rax, -0x2c8(%rbp)
xorl %eax, %eax
movl %eax, %edi
leaq 0x567a(%rip), %rsi      # 0xb556
callq 0x2390
movq %rax, -0x2c8(%rbp)
cmpq $0x0, -0x2c8(%rbp)
je 0x5f1b
movq -0x2c8(%rbp), %rdi
movl $0x10, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x3720
movl %eax, -0x318(%rbp)
jmp 0x5f0f
movl -0x318(%rbp), %eax
movl %eax, -0x2bc(%rbp)
movl $0x0, -0x2cc(%rbp)
movl -0x2cc(%rbp), %eax
cmpl -0x2bc(%rbp), %eax
jge 0x5fd9
movl -0x2b8(%rbp), %edx
movl -0x2cc(%rbp), %eax
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,4), %esi
leaq 0x585c(%rip), %rdi      # 0xb7ad
xorl %eax, %eax
callq 0x2040
jmp 0x5f5a
movl $0x0, -0x2d0(%rbp)
cmpl $0x4, -0x2d0(%rbp)
jge 0x5fb3
movq -0x8(%rbp), %rax
movl -0x2b8(%rbp), %esi
movl -0x2cc(%rbp), %ecx
movl %ecx, %edx
movl %esi, %ecx
leal (%rcx,%rdx,4), %ecx
movl -0x2d0(%rbp), %edx
addl %edx, %ecx
movzbl (%rax,%rcx), %esi
leaq 0x581f(%rip), %rdi      # 0xb7b6
xorl %eax, %eax
callq 0x2040
jmp 0x5fa0
jmp 0x5fa2
movl -0x2d0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2d0(%rbp)
jmp 0x5f64
leaq 0x5858(%rip), %rdi      # 0xb812
xorl %eax, %eax
callq 0x2040
jmp 0x5fc3
jmp 0x5fc5
movl -0x2cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2cc(%rbp)
jmp 0x5f25
jmp 0x5fdb
movsbl -0x1c0(%rbp), %eax
cmpl $0x6c, %eax
jne 0x609c
leaq 0x57ca(%rip), %rdi      # 0xb7bc
xorl %eax, %eax
callq 0x2040
jmp 0x5ffb
leaq 0x57d9(%rip), %rdi      # 0xb7db
xorl %eax, %eax
callq 0x2040
jmp 0x600b
movl $0x0, -0x2d4(%rbp)
cmpl $0x2000, -0x2d4(%rbp)   # imm = 0x2000
jge 0x609a
movq -0x10(%rbp), %rax
movslq -0x2d4(%rbp), %rcx
imulq $0x98, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x2e0(%rbp)
movq -0x2e0(%rbp), %rax
cmpl $0x0, 0x90(%rax)
jl 0x6084
movq -0x2e0(%rbp), %rax
cmpq $0x0, 0x88(%rax)
je 0x6084
movq -0x2e0(%rbp), %rax
movl 0x90(%rax), %esi
movq 0x88(%rax), %rdx
leaq 0x5783(%rip), %rdi      # 0xb7fc
xorl %eax, %eax
callq 0x2040
jmp 0x6082
jmp 0x6084
jmp 0x6086
movl -0x2d4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2d4(%rbp)
jmp 0x6015
jmp 0x609c
movl $0x0, -0x29c(%rbp)
leaq -0x288(%rbp), %rdi
callq 0x2160
movl -0x29c(%rbp), %eax
testl %eax, %eax
je 0x60c0
jmp 0x60be
jmp 0x60c5
jmp 0x59b8
jmp 0x60c7
jmp 0x60c9
movl -0x124(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x2e4(%rbp)
movl -0x268(%rbp), %eax
movq %rax, -0x320(%rbp)
subq $0x26, %rax
ja 0x672b
movq -0x320(%rbp), %rax
leaq 0x4fdf(%rip), %rcx      # 0xb0dc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
addl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
subl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %edx
movslq -0x1e8(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %esi
xorl %ecx, %ecx
movl $0x1, %eax
cmpl %esi, %edx
cmovll %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
addl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
andl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
orl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x1e8(%rbp), %rax
xorl -0xa0(%rbp,%rax,4), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x1e8(%rbp), %rcx
movl -0xa0(%rbp,%rcx,4), %ecx
shll %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x1e8(%rbp), %rcx
movl -0xa0(%rbp,%rcx,4), %ecx
shrl %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x1e8(%rbp), %rcx
movl -0xa0(%rbp,%rcx,4), %ecx
sarl %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
addl -0x1e4(%rbp), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %edx
movl -0x1e4(%rbp), %esi
xorl %ecx, %ecx
movl $0x1, %eax
cmpl %esi, %edx
cmovll %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %edx
movl -0x1e4(%rbp), %esi
xorl %ecx, %ecx
movl $0x1, %eax
cmpl %esi, %edx
cmovbl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
andl -0x1e4(%rbp), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
orl -0x1e4(%rbp), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
xorl -0x1e4(%rbp), %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movl -0x1e4(%rbp), %ecx
shll %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movl -0x1e4(%rbp), %ecx
shrl %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movl -0x1e4(%rbp), %ecx
sarl %cl, %eax
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movq -0x8(%rbp), %rdi
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %esi
addl -0x1e4(%rbp), %esi
movl -0x268(%rbp), %edx
callq 0x39e0
movl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movq -0x8(%rbp), %rdi
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %esi
addl -0x1e4(%rbp), %esi
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %edx
movl -0x268(%rbp), %ecx
callq 0x3880
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
jne 0x650f
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
jl 0x653e
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
jb 0x656d
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
jge 0x659c
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
jae 0x65cb
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movslq -0x240(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x214(%rbp), %rcx
cmpl -0xa0(%rbp,%rcx,4), %eax
je 0x65fa
movl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movl -0x124(%rbp), %ecx
addl $0x4, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
movl -0x210(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movl -0x124(%rbp), %ecx
addl $0x4, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
movslq -0x214(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
addl -0x1e4(%rbp), %eax
movl %eax, -0x2e4(%rbp)
jmp 0x678b
movl -0x124(%rbp), %ecx
movl -0x210(%rbp), %eax
shll $0xc, %eax
addl %eax, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
movl -0x210(%rbp), %ecx
shll $0xc, %ecx
movslq -0x240(%rbp), %rax
movl %ecx, -0xa0(%rbp,%rax,4)
jmp 0x678b
leaq 0x5161(%rip), %rdi      # 0xb805
movb $0x0, %al
callq 0x2040
leaq 0x5162(%rip), %rdi      # 0xb814
movb $0x0, %al
callq 0x2040
movl -0x128(%rbp), %esi
movl -0x124(%rbp), %edx
movl -0x1d8(%rbp), %ecx
leaq 0x516c(%rip), %rdi      # 0xb83e
movb $0x0, %al
callq 0x2040
leaq -0xa0(%rbp), %rdi
callq 0x2cc0
movl 0xc7d5(%rip), %esi      # 0x12ec0
movl 0xc7cb(%rip), %edx      # 0x12ebc
movl 0xc7c1(%rip), %ecx      # 0x12eb8
movl 0xc7b6(%rip), %r8d      # 0x12eb4
leaq 0x5159(%rip), %rdi      # 0xb85e
movb $0x0, %al
callq 0x2040
movl 0xc79e(%rip), %esi      # 0x12eb0
leaq 0x5169(%rip), %rdi      # 0xb882
movb $0x0, %al
callq 0x2040
movb $0x1, -0x1c9(%rbp)
jmp 0x678b
jmp 0x672b
leaq 0x5167(%rip), %rdi      # 0xb899
movb $0x0, %al
callq 0x2040
cmpq $0x0, -0x1e0(%rbp)
je 0x6758
movq -0x1e0(%rbp), %rsi
leaq 0x516f(%rip), %rdi      # 0xb8c0
movb $0x0, %al
callq 0x2040
movl -0x128(%rbp), %esi
movl -0x124(%rbp), %edx
movl -0x1d8(%rbp), %ecx
leaq 0x50cd(%rip), %rdi      # 0xb83e
movb $0x0, %al
callq 0x2040
leaq -0xa0(%rbp), %rdi
callq 0x2cc0
movb $0x1, -0x1c9(%rbp)
movl -0x2e4(%rbp), %eax
movl $0x10000, %ecx          # imm = 0x10000
cltd
idivl %ecx
movl %edx, -0x124(%rbp)
movl $0x0, -0xa0(%rbp)
testb $0x1, -0x12d(%rbp)
je 0x6849
movl $0x0, -0x2e8(%rbp)
cmpl $0x20, -0x2e8(%rbp)
jge 0x6847
movslq -0x2e8(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %eax
movslq -0x2e8(%rbp), %rcx
cmpl -0x120(%rbp,%rcx,4), %eax
je 0x6817
movl -0x2e8(%rbp), %esi
movslq -0x2e8(%rbp), %rax
movl -0x120(%rbp,%rax,4), %edx
movslq -0x2e8(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
leaq 0x50c1(%rip), %rdi      # 0xb8d1
movb $0x0, %al
callq 0x2040
movslq -0x2e8(%rbp), %rax
movl -0xa0(%rbp,%rax,4), %ecx
movslq -0x2e8(%rbp), %rax
movl %ecx, -0x120(%rbp,%rax,4)
movl -0x2e8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2e8(%rbp)
jmp 0x67c0
jmp 0x6849
movq 0x8768(%rip), %rax      # 0xefb8
movq (%rax), %rdi
callq 0x2230
jmp 0x58ea
addq $0x320, %rsp            # imm = 0x320
popq %rbp
retq
movq -0x290(%rbp), %rdi
callq 0x23e0
nopw %cs:(%rax,%rax)