// File: /workspace/github_cpp_makefile_star2_O3/QFSW[P]MIPS1-Simulator/src/Instructions.cpp
// Function: Clarkitechture::MIPS::BinaryDecoder::decodeRInstruction(unsigned int)
RInstruction* BinaryDecoder::decodeRInstruction(uint32_t bin)
{
	byte rs = 0b11111 & (bin >> (32 - (6 + 5)));
	byte rt = 0b11111 & (bin >> (32 - (6 + 5 + 5)));
	byte rd = 0b11111 & (bin >> (32 - (6 + 5 + 5 + 5)));
	byte shamt = 0b11111 & (bin >> (32 - (6 + 5 + 5 + 5 + 5)));
	byte funct = 0b111111 & bin;

	switch (funct)
	{
    case 0b100000: return new ADDInstr(rs, rt, rd, shamt);
    case 0b100001: return new ADDUInstr(rs, rt, rd, shamt);
    case 0b100010: return new SUBInstr(rs, rt, rd, shamt);
    case 0b100011: return new SUBUInstr(rs, rt, rd, shamt);
    case 0b100100: return new ANDInstr(rs, rt, rd, shamt);
    case 0b100101: return new ORInstr(rs, rt, rd, shamt);
    case 0b100111: return new NORInstr(rs, rt, rd, shamt);
    case 0b100110: return new XORInstr(rs, rt, rd, shamt);
    case 0b001000: return new JRInstr(rs, rt, rd, shamt);
    case 0b001001: return new JALRInstr(rs, rt, rd, shamt);
    case 0b011000: return new MULTInstr(rs, rt, rd, shamt);
    case 0b011001: return new MULTUInstr(rs, rt, rd, shamt);
    case 0b011010: return new DIVInstr(rs, rt, rd, shamt);
    case 0b011011: return new DIVUInstr(rs, rt, rd, shamt);
    case 0b010000: return new MFHIInstr(rs, rt, rd, shamt);
    case 0b010010: return new MFLOInstr(rs, rt, rd, shamt);
    case 0b010001: return new MTHIInstr(rs, rt, rd, shamt);
    case 0b010011: return new MTLOInstr(rs, rt, rd, shamt);
    case 0b101010: return new SLTInstr(rs, rt, rd, shamt);
    case 0b101011: return new SLTUInstr(rs, rt, rd, shamt);
    case 0b000000: return new SLLInstr(rs, rt, rd, shamt);
    case 0b000100: return new SLLVInstr(rs, rt, rd, shamt);
    case 0b000011: return new SRAInstr(rs, rt, rd, shamt);
    case 0b000111: return new SRAVInstr(rs, rt, rd, shamt);
    case 0b000010: return new SRLInstr(rs, rt, rd, shamt);
    case 0b000110: return new SRLVInstr(rs, rt, rd, shamt);
    default:
        throw BadInstructionDecode(bin, "invalid or unsupported function code - " + toBinStr(funct));
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x40, %rsp
movl %edi, %ebp
movl %edi, %r14d
andl $0x3f, %r14d
cmpl $0x2c, %r14d
jae 0x825d
movabsq $0xcff0f0f03dd, %rax    # imm = 0xCFF0F0F03DD
btq %r14, %rax
jae 0x825d
movl %r14d, %eax
leaq 0x8369(%rip), %rcx      # 0x10570
movq (%rcx,%rax,8), %rbx
movl %ebp, %r14d
shrl $0x6, %r14d
andb $0x1f, %r14b
movl %ebp, %r15d
shrl $0xb, %r15d
andb $0x1f, %r15b
movl %ebp, %r12d
shrl $0x10, %r12d
andb $0x1f, %r12b
shrl $0x15, %ebp
andb $0x1f, %bpl
movl $0x10, %edi
callq 0x5200
movb %bpl, 0x8(%rax)
movb %r12b, 0x9(%rax)
movb %r15b, 0xa(%rax)
movb %r14b, 0xb(%rax)
movq %rbx, (%rax)
addq $0x40, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movl $0x50, %edi
callq 0x5100
movq %rax, %rbx
movq %rsp, %rdi
movl %r14d, %esi
callq 0x89ed
leaq 0x369f(%rip), %rsi      # 0xb91b
leaq 0x20(%rsp), %rdi
movq %rsp, %rdx
callq 0x897d
movb $0x1, %r15b
leaq 0x20(%rsp), %rdx
movq %rbx, %rdi
movl %ebp, %esi
callq 0x5b82
xorl %r15d, %r15d
leaq 0x7b13(%rip), %rsi      # 0xfdb8
leaq -0x1baa(%rip), %rdx     # 0x6702
movq %rbx, %rdi
callq 0x5380
movq %rax, %r14
leaq 0x30(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x82d2
movq 0x30(%rsp), %rsi
incq %rsi
callq 0x5210
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x82ed
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x5210
testb %r15b, %r15b
jne 0x8317
jmp 0x831f
movq %rax, %r14
leaq 0x10(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x8317
movq 0x10(%rsp), %rsi
incq %rsi
callq 0x5210
jmp 0x8317
movq %rax, %r14
movq %rbx, %rdi
callq 0x5190
movq %r14, %rdi
callq 0x53a0
nop