// File: QFSW[P]MIPS1-Simulator/src/Instructions.cpp
// Function: Clarkitechture::MIPS::BinaryDecoder::decodeIInstruction(unsigned int)
IInstruction* BinaryDecoder::decodeIInstruction(uint32_t bin)
{
	byte opcode = 0b111111 & (bin >> (32 - 6));
	byte rs = 0b11111 & (bin >> (32 - (6 + 5)));
	byte rt = 0b11111 & (bin >> (32 - (6 + 5 + 5)));
	uint16_t constant = 0xFFFF & bin;

	switch (opcode)
	{
	case 0b001000: return new ADDIInstr(rs, rt, constant);
    case 0b001001: return new ADDIUInstr(rs, rt, constant);
	case 0b001100: return new ANDIInstr(rs, rt, constant);
    case 0b001101: return new ORIInstr(rs, rt, constant);
    case 0b001110: return new XORIInstr(rs, rt, constant);
    case 0b001010: return new SLTIInstr(rs, rt, constant);
    case 0b001011: return new SLTIUInstr(rs, rt, constant);
    case 0b001111: return new LUIInstr(rs, rt, constant);
    case 0b100011: return new LWInstr(rs, rt, constant);
    case 0b100000: return new LBInstr(rs, rt, constant);
    case 0b100100: return new LBUInstr(rs, rt, constant);
    case 0b100001: return new LHInstr(rs, rt, constant);
    case 0b100101: return new LHUInstr(rs, rt, constant);
    case 0b101011: return new SWInstr(rs, rt, constant);
    case 0b101000: return new SBInstr(rs, rt, constant);
    case 0b101001: return new SHInstr(rs, rt, constant);
    case 0b000100: return new BEQInstr(rs, rt, constant);
    case 0b000111: return new BGTZInstr(rs, rt, constant);
    case 0b000110: return new BLEZInstr(rs, rt, constant);
    case 0b000101: return new BNEInstr(rs, rt, constant);
    case 0b100010: return new LWLInstr(rs, rt, constant);
    case 0b100110: return new LWRInstr(rs, rt, constant);
    case 0b000001: return decodeBranchInstruction(bin);
    default:
		throw BadInstructionDecode(bin, "invalid or unsupported opcode - " + toBinStr(opcode));
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
movl %edi, -0xc(%rbp)
movl -0xc(%rbp), %eax
shrl $0x1a, %eax
movb %al, -0xd(%rbp)
movl -0xc(%rbp), %eax
shrl $0x15, %eax
andb $0x1f, %al
movb %al, -0xe(%rbp)
movb -0xa(%rbp), %al
andb $0x1f, %al
movb %al, -0xf(%rbp)
movw -0xc(%rbp), %ax
movw %ax, -0x12(%rbp)
movzbl -0xd(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x78(%rbp)
subl $0x2a, %eax
ja 0xd27b
movq -0x78(%rbp), %rax
leaq 0x7e22(%rip), %rcx      # 0x148a4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x80(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe340
jmp 0xcab2
movq -0x80(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x80(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x88(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe3a0
jmp 0xcb08
movq -0x88(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x88(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x90(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe400
jmp 0xcb64
movq -0x90(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x90(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x98(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe460
jmp 0xcbc0
movq -0x98(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x98(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe4c0
jmp 0xcc1c
movq -0xa0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xa0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe520
jmp 0xcc78
movq -0xa8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xa8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe580
jmp 0xccd4
movq -0xb0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xb0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe5e0
jmp 0xcd30
movq -0xb8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xb8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe640
jmp 0xcd8c
movq -0xc0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xc0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe6a0
jmp 0xcde8
movq -0xc8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe700
jmp 0xce44
movq -0xd0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xd0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xd8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe760
jmp 0xcea0
movq -0xd8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xd8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe7c0
jmp 0xcefc
movq -0xe0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xe0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe820
jmp 0xcf58
movq -0xe8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xf0(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe880
jmp 0xcfb4
movq -0xf0(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xf0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xf8(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe8e0
jmp 0xd010
movq -0xf8(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0xf8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x18, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x100(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe940
jmp 0xd06c
movq -0x100(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x100(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x18, %esi
callq 0x62b0
jmp 0xd353
movl $0x18, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x108(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xe9a0
jmp 0xd0c8
movq -0x108(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x108(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x18, %esi
callq 0x62b0
jmp 0xd353
movl $0x18, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x110(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xea00
jmp 0xd124
movq -0x110(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x110(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x18, %esi
callq 0x62b0
jmp 0xd353
movl $0x18, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x118(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xea60
jmp 0xd180
movq -0x118(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x118(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x18, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x120(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xeac0
jmp 0xd1dc
movq -0x120(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl $0x10, %edi
callq 0x62a0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x128(%rbp)
movzbl -0xe(%rbp), %esi
movzbl -0xf(%rbp), %edx
movzwl -0x12(%rbp), %ecx
callq 0xeb20
jmp 0xd238
movq -0x128(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0xd346
movq -0x128(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x10, %esi
callq 0x62b0
jmp 0xd353
movl -0xc(%rbp), %edi
callq 0xd360
movq %rax, -0x8(%rbp)
jmp 0xd346
movb $0x1, -0x69(%rbp)
movl $0x50, %edi
callq 0x6140
movq %rax, -0x138(%rbp)
movl -0xc(%rbp), %eax
movl %eax, -0x12c(%rbp)
movzbl -0xd(%rbp), %esi
leaq -0x68(%rbp), %rdi
callq 0xe220
jmp 0xd2a8
leaq 0x778c(%rip), %rsi      # 0x14a3b
leaq -0x48(%rbp), %rdi
leaq -0x68(%rbp), %rdx
callq 0x7350
jmp 0xd2be
movl -0x12c(%rbp), %esi
movq -0x138(%rbp), %rdi
leaq -0x48(%rbp), %rdx
callq 0x6b50
jmp 0xd2d6
movq -0x138(%rbp), %rdi
movb $0x0, -0x69(%rbp)
leaq 0xebf0(%rip), %rsi      # 0x1bed8
leaq -0x5aaf(%rip), %rdx     # 0x7840
callq 0x6470
jmp 0xd35c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0xd330
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
jmp 0xd327
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x6190
leaq -0x68(%rbp), %rdi
callq 0x6190
testb $0x1, -0x69(%rbp)
jne 0xd338
jmp 0xd344
movq -0x138(%rbp), %rdi
callq 0x61f0
jmp 0xd353
movq -0x8(%rbp), %rax
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x64b0
nopl (%rax)