// File: ys1998[P]spsim/src/decoder.cpp
// Function: Decoder::decode_instr(Instruction)
int Decoder::decode_instr(Instruction instr){
	std::tuple<int, int, int> reg = instr.logical_regs();
	std::tuple<int,int> instruction_type = instr.type();
	int opcode = std::get<0>(instruction_type);
	
	int rs = std::get<0>(reg);
	int rt = std::get<1>(reg);
	int rd = std::get<2>(reg);
	
	int temp, rs_, rt_, rd_;
	temp = rs_ = rt_ = rd_ = -1;
	bool found[3] = {false, false, false};

	if(*(r + rs) == -1){
		if((temp = f->find()) == -1)
			return -1;
		*(r + rs) = rs_ = temp;
		f->remove(rs_);
		found[0] = true;
	} else {
		rs_ = *(r + rs);
	}
	if(*(r + rt) == -1){
		if((temp = f->find()) == -1){
			if(found[0]){
				f->add(rs_);
				*(r + rs) = -1;	
			} 	// add already removed register
			return -1;
		}
		*(r + rt) = rt_ = temp;
		f->remove(rt_);
		found[1] = true;
	} else {
		rt_ = *(r + rt);
	}
	if(opcode == OPCODE["lw"] || opcode == 0){
		if((temp = f->find()) == -1){
			if(found[0]) {
				f->add(rs_);
				*(r + rs) = -1;
			}	// add already removed register
			if(found[1]) {
				f->add(rt_);
				*(r + rt) = -1;
			}
			return -1;
		} 
		rd_ = temp;
		f->remove(rd_);	
	}
	if(rd != -1)
		instr.map(std::make_tuple(rs_, rt_, rd_, *(r + rd)));
	else
		instr.map(std::make_tuple(rs_, rt_, rd_, -1));
	
	if(opcode == OPCODE["lw"] || opcode == 0){
		*(r + rd) = temp;
		*(b + rd_) = true;
	}

	int ret = 0;
	if(opcode == OPCODE["beq"] || opcode == OPCODE["bne"]){
		auto pr = predict_branch(instr.get_pc());
		instr.predicted = std::get<0>(pr);
		instr.jumpAddressPred = std::get<1>(pr);
		if(instr.predicted){
			ret = 1;
			ft->update_PC(instr.jumpAddressPred);
		}
	}

	instr.DE = CLOCK;
	instr.RF1 = CLOCK + 1;
	instr.set_id();

	if(!(opcode == OPCODE["lw"] || opcode == OPCODE["sw"]))
		iq->add(instr); // TODO check return value
	else
		aq->add(instr);
	
	a->push(instr); // TODO check return value
	return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3e0, %rsp            # imm = 0x3E0
movq %rsi, -0x2f0(%rbp)
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x2e8(%rbp)
leaq -0x24(%rbp), %rdi
callq 0x10570
movq -0x2f0(%rbp), %rsi
leaq -0x2c(%rbp), %rdi
callq 0x105b0
leaq -0x2c(%rbp), %rdi
callq 0xa9d0
movl (%rax), %eax
movl %eax, -0x30(%rbp)
leaq -0x24(%rbp), %rdi
callq 0xa9f0
movl (%rax), %eax
movl %eax, -0x34(%rbp)
leaq -0x24(%rbp), %rdi
callq 0xaa10
movl (%rax), %eax
movl %eax, -0x38(%rbp)
leaq -0x24(%rbp), %rdi
callq 0xaa30
movl (%rax), %eax
movl %eax, -0x3c(%rbp)
movl $0xffffffff, -0x4c(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x48(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x44(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x40(%rbp) # imm = 0xFFFFFFFF
leaq -0x4f(%rbp), %rdi
xorl %esi, %esi
movl $0x3, %edx
callq 0x3190
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x34(%rbp), %rcx
cmpl $-0x1, (%rax,%rcx,4)
jne 0x9ca5
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x13500
movl %eax, -0x40(%rbp)
cmpl $-0x1, %eax
jne 0x9c7b
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa64a
movq -0x2e8(%rbp), %rax
movl -0x40(%rbp), %esi
movl %esi, -0x44(%rbp)
movq 0x70(%rax), %rcx
movslq -0x34(%rbp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x60(%rax), %rdi
movl -0x44(%rbp), %esi
callq 0x13060
movb $0x1, -0x4f(%rbp)
jmp 0x9cba
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x34(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x44(%rbp)
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x38(%rbp), %rcx
cmpl $-0x1, (%rax,%rcx,4)
jne 0x9d4c
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x13500
movl %eax, -0x40(%rbp)
cmpl $-0x1, %eax
jne 0x9d22
testb $0x1, -0x4f(%rbp)
je 0x9d16
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
movl -0x44(%rbp), %esi
callq 0x12bc0
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x34(%rbp), %rcx
movl $0xffffffff, (%rax,%rcx,4) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa64a
movq -0x2e8(%rbp), %rax
movl -0x40(%rbp), %esi
movl %esi, -0x48(%rbp)
movq 0x70(%rax), %rcx
movslq -0x38(%rbp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x60(%rax), %rdi
movl -0x48(%rbp), %esi
callq 0x13060
movb $0x1, -0x4e(%rbp)
jmp 0x9d61
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x38(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x48(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0x2fc(%rbp)
leaq -0x71(%rbp), %rdi
movq %rdi, -0x2f8(%rbp)
callq 0x3490
movq -0x2f8(%rbp), %rdx
leaq 0x182e5(%rip), %rsi     # 0x2206d
leaq -0x70(%rbp), %rdi
callq 0x6020
jmp 0x9d93
leaq 0x2552e(%rip), %rdi     # 0x2f2c8
leaq -0x70(%rbp), %rsi
callq 0x5f40
movq %rax, -0x308(%rbp)
jmp 0x9dac
movl -0x2fc(%rbp), %ecx
movq -0x308(%rbp), %rdx
movb $0x1, %al
cmpl (%rdx), %ecx
movb %al, -0x309(%rbp)
je 0x9dd2
cmpl $0x0, -0x30(%rbp)
sete %al
movb %al, -0x309(%rbp)
movb -0x309(%rbp), %al
movb %al, -0x30a(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x31e0
leaq -0x71(%rbp), %rdi
callq 0x3300
movb -0x30a(%rbp), %al
testb $0x1, %al
jne 0x9dff
jmp 0x9ed7
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
callq 0x13500
movl %eax, -0x40(%rbp)
cmpl $-0x1, %eax
jne 0x9ebe
testb $0x1, -0x4f(%rbp)
je 0x9e83
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
movl -0x44(%rbp), %esi
callq 0x12bc0
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x34(%rbp), %rcx
movl $0xffffffff, (%rax,%rcx,4) # imm = 0xFFFFFFFF
jmp 0x9e83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x9e75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x31e0
leaq -0x71(%rbp), %rdi
callq 0x3300
jmp 0xa656
testb $0x1, -0x4e(%rbp)
je 0x9eb2
movq -0x2e8(%rbp), %rax
movq 0x60(%rax), %rdi
movl -0x48(%rbp), %esi
callq 0x12bc0
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %rax
movslq -0x38(%rbp), %rcx
movl $0xffffffff, (%rax,%rcx,4) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa64a
movq -0x2e8(%rbp), %rax
movl -0x40(%rbp), %ecx
movl %ecx, -0x4c(%rbp)
movq 0x60(%rax), %rdi
movl -0x4c(%rbp), %esi
callq 0x13060
cmpl $-0x1, -0x3c(%rbp)
je 0x9f20
movq -0x2e8(%rbp), %rax
movq 0x70(%rax), %r8
movslq -0x3c(%rbp), %rax
shlq $0x2, %rax
addq %rax, %r8
leaq -0x94(%rbp), %rdi
leaq -0x44(%rbp), %rsi
leaq -0x48(%rbp), %rdx
leaq -0x4c(%rbp), %rcx
callq 0xaa50
movq -0x2f0(%rbp), %rdi
leaq -0x94(%rbp), %rsi
callq 0x104a0
jmp 0x9f5c
movl $0xffffffff, -0xa8(%rbp) # imm = 0xFFFFFFFF
leaq -0xa4(%rbp), %rdi
leaq -0x44(%rbp), %rsi
leaq -0x48(%rbp), %rdx
leaq -0x4c(%rbp), %rcx
leaq -0xa8(%rbp), %r8
callq 0xaaa0
movq -0x2f0(%rbp), %rdi
leaq -0xa4(%rbp), %rsi
callq 0x104a0
movl -0x30(%rbp), %eax
movl %eax, -0x31c(%rbp)
leaq -0xc9(%rbp), %rdi
movq %rdi, -0x318(%rbp)
callq 0x3490
movq -0x318(%rbp), %rdx
leaq 0x180e7(%rip), %rsi     # 0x2206d
leaq -0xc8(%rbp), %rdi
callq 0x6020
jmp 0x9f94
leaq 0x2532d(%rip), %rdi     # 0x2f2c8
leaq -0xc8(%rbp), %rsi
callq 0x5f40
movq %rax, -0x328(%rbp)
jmp 0x9fb0
movl -0x31c(%rbp), %ecx
movq -0x328(%rbp), %rdx
movb $0x1, %al
cmpl (%rdx), %ecx
movb %al, -0x329(%rbp)
je 0x9fd6
cmpl $0x0, -0x30(%rbp)
sete %al
movb %al, -0x329(%rbp)
movb -0x329(%rbp), %al
movb %al, -0x32a(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x31e0
leaq -0xc9(%rbp), %rdi
callq 0x3300
movb -0x32a(%rbp), %al
testb $0x1, %al
jne 0xa006
jmp 0xa066
movq -0x2e8(%rbp), %rax
movl -0x40(%rbp), %esi
movq 0x70(%rax), %rcx
movslq -0x3c(%rbp), %rdx
movl %esi, (%rcx,%rdx,4)
movq 0x78(%rax), %rax
movslq -0x4c(%rbp), %rcx
movb $0x1, (%rax,%rcx)
jmp 0xa066
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa055
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x31e0
leaq -0xc9(%rbp), %rdi
callq 0x3300
jmp 0xa656
movl $0x0, -0xd0(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0x33c(%rbp)
leaq -0xf1(%rbp), %rdi
movq %rdi, -0x338(%rbp)
callq 0x3490
movq -0x338(%rbp), %rdx
movb $0x0, -0x11a(%rbp)
movb $0x0, -0x11b(%rbp)
leaq 0x17f64(%rip), %rsi     # 0x2200c
leaq -0xf0(%rbp), %rdi
callq 0x6020
jmp 0xa0b6
leaq 0x2520b(%rip), %rdi     # 0x2f2c8
leaq -0xf0(%rbp), %rsi
callq 0x5f40
movq %rax, -0x348(%rbp)
jmp 0xa0d2
movl -0x33c(%rbp), %ecx
movq -0x348(%rbp), %rdx
movb $0x1, %al
cmpl (%rdx), %ecx
movb %al, -0x349(%rbp)
je 0xa165
movl -0x30(%rbp), %eax
movl %eax, -0x35c(%rbp)
leaq -0x119(%rbp), %rdi
movq %rdi, -0x358(%rbp)
callq 0x3490
movq -0x358(%rbp), %rdx
movb $0x1, -0x11a(%rbp)
leaq 0x17ef4(%rip), %rsi     # 0x22010
leaq -0x118(%rbp), %rdi
callq 0x6020
jmp 0xa12a
movb $0x1, -0x11b(%rbp)
leaq 0x25190(%rip), %rdi     # 0x2f2c8
leaq -0x118(%rbp), %rsi
callq 0x5f40
movq %rax, -0x368(%rbp)
jmp 0xa14d
movl -0x35c(%rbp), %eax
movq -0x368(%rbp), %rcx
cmpl (%rcx), %eax
sete %al
movb %al, -0x349(%rbp)
movb -0x349(%rbp), %al
movb %al, -0x369(%rbp)
testb $0x1, -0x11b(%rbp)
jne 0xa17c
jmp 0xa188
leaq -0x118(%rbp), %rdi
callq 0x31e0
testb $0x1, -0x11a(%rbp)
jne 0xa193
jmp 0xa19f
leaq -0x119(%rbp), %rdi
callq 0x3300
leaq -0xf0(%rbp), %rdi
callq 0x31e0
leaq -0xf1(%rbp), %rdi
callq 0x3300
movb -0x369(%rbp), %al
testb $0x1, %al
jne 0xa1c6
jmp 0xa2e6
movq -0x2f0(%rbp), %rdi
callq 0x6230
movq -0x2e8(%rbp), %rsi
movl %eax, %edx
leaq -0x124(%rbp), %rdi
callq 0xa660
leaq -0x124(%rbp), %rdi
callq 0xa9d0
movq %rax, %rcx
movq -0x2f0(%rbp), %rax
movl (%rcx), %ecx
movl %ecx, 0x70(%rax)
leaq -0x124(%rbp), %rdi
callq 0xaaf0
movq %rax, %rcx
movq -0x2f0(%rbp), %rax
movl (%rcx), %ecx
movl %ecx, 0x74(%rax)
cmpl $0x0, 0x70(%rax)
je 0xa2e4
movq -0x2f0(%rbp), %rax
movq -0x2e8(%rbp), %rcx
movl $0x1, -0xd0(%rbp)
movq 0xa8(%rcx), %rdi
movl 0x74(%rax), %esi
callq 0xdd90
jmp 0xa2e4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa2d3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa2c7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa2ae
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
testb $0x1, -0x11b(%rbp)
jne 0xa2a0
jmp 0xa2ac
leaq -0x118(%rbp), %rdi
callq 0x31e0
jmp 0xa2ae
testb $0x1, -0x11a(%rbp)
jne 0xa2b9
jmp 0xa2c5
leaq -0x119(%rbp), %rdi
callq 0x3300
jmp 0xa2c7
leaq -0xf0(%rbp), %rdi
callq 0x31e0
leaq -0xf1(%rbp), %rdi
callq 0x3300
jmp 0xa656
jmp 0xa2e6
movq -0x2f0(%rbp), %rdi
leaq 0x24fc8(%rip), %rax     # 0x2f2bc
movl (%rax), %ecx
movl %ecx, 0x38(%rdi)
movl (%rax), %eax
incl %eax
movl %eax, 0x3c(%rdi)
callq 0xab10
movl -0x30(%rbp), %eax
movl %eax, -0x37c(%rbp)
leaq -0x149(%rbp), %rdi
movq %rdi, -0x378(%rbp)
callq 0x3490
movq -0x378(%rbp), %rdx
movb $0x0, -0x172(%rbp)
movb $0x0, -0x173(%rbp)
leaq 0x17d30(%rip), %rsi     # 0x2206d
leaq -0x148(%rbp), %rdi
callq 0x6020
jmp 0xa34b
leaq 0x24f76(%rip), %rdi     # 0x2f2c8
leaq -0x148(%rbp), %rsi
callq 0x5f40
movq %rax, -0x388(%rbp)
jmp 0xa367
movl -0x37c(%rbp), %ecx
movq -0x388(%rbp), %rdx
movb $0x1, %al
cmpl (%rdx), %ecx
movb %al, -0x389(%rbp)
je 0xa3fa
movl -0x30(%rbp), %eax
movl %eax, -0x39c(%rbp)
leaq -0x171(%rbp), %rdi
movq %rdi, -0x398(%rbp)
callq 0x3490
movq -0x398(%rbp), %rdx
movb $0x1, -0x172(%rbp)
leaq 0x17c6c(%rip), %rsi     # 0x2201d
leaq -0x170(%rbp), %rdi
callq 0x6020
jmp 0xa3bf
movb $0x1, -0x173(%rbp)
leaq 0x24efb(%rip), %rdi     # 0x2f2c8
leaq -0x170(%rbp), %rsi
callq 0x5f40
movq %rax, -0x3a8(%rbp)
jmp 0xa3e2
movl -0x39c(%rbp), %eax
movq -0x3a8(%rbp), %rcx
cmpl (%rcx), %eax
sete %al
movb %al, -0x389(%rbp)
movb -0x389(%rbp), %al
xorb $-0x1, %al
movb %al, -0x3a9(%rbp)
testb $0x1, -0x173(%rbp)
jne 0xa413
jmp 0xa41f
leaq -0x170(%rbp), %rdi
callq 0x31e0
testb $0x1, -0x172(%rbp)
jne 0xa42a
jmp 0xa436
leaq -0x171(%rbp), %rdi
callq 0x3300
leaq -0x148(%rbp), %rdi
callq 0x31e0
leaq -0x149(%rbp), %rdi
callq 0x3300
movb -0x3a9(%rbp), %al
testb $0x1, %al
jne 0xa45d
jmp 0xa563
movq -0x2f0(%rbp), %rsi
movq -0x2e8(%rbp), %rax
movq 0x80(%rax), %rax
movq %rax, -0x3c0(%rbp)
leaq -0x1f0(%rbp), %rdi
movq %rdi, -0x3b8(%rbp)
callq 0x6c70
movq -0x3c0(%rbp), %rdi
movq -0x3b8(%rbp), %rsi
callq 0x1b3a0
jmp 0xa4a1
leaq -0x1f0(%rbp), %rdi
callq 0x61d0
jmp 0xa5d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa532
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa526
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0xa50d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
testb $0x1, -0x173(%rbp)
jne 0xa4ff
jmp 0xa50b
leaq -0x170(%rbp), %rdi
callq 0x31e0
jmp 0xa50d
testb $0x1, -0x172(%rbp)
jne 0xa518
jmp 0xa524
leaq -0x171(%rbp), %rdi
callq 0x3300
jmp 0xa526
leaq -0x148(%rbp), %rdi
callq 0x31e0
leaq -0x149(%rbp), %rdi
callq 0x3300
jmp 0xa656
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x1f0(%rbp), %rdi
callq 0x61d0
jmp 0xa656
movq -0x2f0(%rbp), %rsi
movq -0x2e8(%rbp), %rax
movq 0x88(%rax), %rax
movq %rax, -0x3d0(%rbp)
leaq -0x268(%rbp), %rdi
movq %rdi, -0x3c8(%rbp)
callq 0x6c70
movq -0x3d0(%rbp), %rdi
movq -0x3c8(%rbp), %rsi
callq 0x1c6e0
jmp 0xa5a7
leaq -0x268(%rbp), %rdi
callq 0x61d0
jmp 0xa5d5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x268(%rbp), %rdi
callq 0x61d0
jmp 0xa656
movq -0x2f0(%rbp), %rsi
movq -0x2e8(%rbp), %rax
movq 0x68(%rax), %rax
movq %rax, -0x3e0(%rbp)
leaq -0x2e0(%rbp), %rdi
movq %rdi, -0x3d8(%rbp)
callq 0x6c70
movq -0x3e0(%rbp), %rdi
movq -0x3d8(%rbp), %rsi
callq 0x135b0
jmp 0xa616
leaq -0x2e0(%rbp), %rdi
callq 0x61d0
movl -0xd0(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0xa64a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x61d0
jmp 0xa656
movl -0x4(%rbp), %eax
addq $0x3e0, %rsp            # imm = 0x3E0
popq %rbp
retq
movq -0x80(%rbp), %rdi
callq 0x3480
nop