// File: pollow[P]MIPSClide/instruction.cpp
// Function: Instruction::compile()
unsigned int Instruction::compile() {
    unsigned long result = 0;
    if ( !opcode.count(command) ) {
        throw invalid_argument("No such command"); 
    }
    switch ( type ) {
        case 'R':
            result += opcode[command] << 26;
            if (reg_num == 1) {
                if ( !regs.count(reg1) ) {
                    throw invalid_argument("No such register"); 
                }
                if ( command == "mfhi" || command == "mflo" ) {
                    result += regs[reg1] << 11;
                } else {
                    result += regs[reg1] << 21;
                }
            } else if ( reg_num == 2 ) {
                if ( !(regs.count(reg1) && regs.count(reg2)) ) {
                    throw invalid_argument("No such register"); 
                }
                if(has_shamt) {
                    result += (regs[reg1] << 11) + (regs[reg2] << 16);
                    result += shamt << 6;
                } else if ( command == "jarl" ) {
                    result += (regs[reg1] << 21) + (regs[reg2] << 11);
                } else if ( command == "clo" || command == "clz" ) {
                    result += (regs[reg1] << 11) + (regs[reg2] << 21);
                } else {
                    result += (regs[reg1] << 21) + (regs[reg2] << 16);
                }
            } else {
                if ( !(regs.count(reg1) && regs.count(reg2) && regs.count(reg3)) ) {
                    throw invalid_argument("No such register"); 
                }
                result += (regs[reg1] << 11) + (regs[reg2] << 21) + (regs[reg3] << 16);
            }
            result += func[command];
            break;
        case 'I':
            result += opcode[command] << 26;
            if (reg_num == 1) {
                if (command == "lui") result += regs[reg1] << 16;
                else result += regs[reg1] << 21;
            }
            if (reg_num == 2) {
                if (command == "beq" || command == "bne") {
                    result += regs[reg2] << 16;
                    result += regs[reg1] << 21;
                } else {
                    result += regs[reg1] << 16;
                    result += regs[reg2] << 21;
                }
            }
            result += imm;
            break;
        case 'J':
            result += opcode[command] << 26;
            result += imm;
            break;
    }

    return result;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rsi
movq %rsi, -0x28(%rbp)
movq $0x0, -0x10(%rbp)
leaq 0x28f9d(%rip), %rdi     # 0x6bab0
callq 0x45630
cmpq $0x0, %rax
jne 0x42b71
movl $0x10, %edi
callq 0x6210
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x30(%rbp)
leaq 0x89b7(%rip), %rsi      # 0x4b4f0
callq 0x6820
jmp 0x42b40
movq -0x30(%rbp), %rdi
movq 0x28485(%rip), %rsi     # 0x6afd0
movq 0x28466(%rip), %rdx     # 0x6afb8
callq 0x6730
movq -0x30(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x6350
jmp 0x431d0
movq -0x28(%rbp), %rax
movsbl 0x90(%rax), %eax
movl %eax, -0x34(%rbp)
subl $0x49, %eax
je 0x4301a
jmp 0x42b8a
movl -0x34(%rbp), %eax
subl $0x4a, %eax
je 0x4318d
jmp 0x42b98
movl -0x34(%rbp), %eax
subl $0x52, %eax
jne 0x431c6
jmp 0x42ba6
movq -0x28(%rbp), %rsi
leaq 0x28eff(%rip), %rdi     # 0x6bab0
callq 0x45690
movq %rax, %rcx
movq -0x28(%rbp), %rax
movl (%rcx), %ecx
shll $0x1a, %ecx
movl %ecx, %ecx
addq -0x10(%rbp), %rcx
movq %rcx, -0x10(%rbp)
cmpl $0x1, 0x80(%rax)
jne 0x42cbd
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x29078(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
jne 0x42c46
movl $0x10, %edi
callq 0x6210
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x40(%rbp)
leaq 0x88f2(%rip), %rsi      # 0x4b500
callq 0x6820
jmp 0x42c15
movq -0x40(%rbp), %rdi
movq 0x283b0(%rip), %rsi     # 0x6afd0
movq 0x28391(%rip), %rdx     # 0x6afb8
callq 0x6730
movq -0x40(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x6350
jmp 0x431d0
movq -0x28(%rbp), %rdi
leaq 0x8783(%rip), %rsi      # 0x4b3d4
callq 0x15570
testb $0x1, %al
jne 0x42c70
movq -0x28(%rbp), %rdi
leaq 0x8774(%rip), %rsi      # 0x4b3d9
callq 0x15570
testb $0x1, %al
jne 0x42c70
jmp 0x42c95
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28fe1(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0xb, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42cb8
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28fbc(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0x15, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ffb
movq -0x28(%rbp), %rax
cmpl $0x2, 0x80(%rax)
jne 0x42eed
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28f83(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
je 0x42d02
movq -0x28(%rbp), %rsi
addq $0x40, %rsi
leaq 0x28f69(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
jne 0x42d55
movl $0x10, %edi
callq 0x6210
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x48(%rbp)
leaq 0x87e3(%rip), %rsi      # 0x4b500
callq 0x6820
jmp 0x42d24
movq -0x48(%rbp), %rdi
movq 0x282a1(%rip), %rsi     # 0x6afd0
movq 0x28282(%rip), %rdx     # 0x6afb8
callq 0x6730
movq -0x48(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x6350
jmp 0x431d0
movq -0x28(%rbp), %rax
testb $0x1, 0x91(%rax)
je 0x42dc8
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28eef(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0xb, %eax
movl %eax, -0x4c(%rbp)
addq $0x40, %rsi
leaq 0x28ed3(%rip), %rdi     # 0x6bc60
callq 0x45690
movl -0x4c(%rbp), %ecx
movq %rax, %rdx
movq -0x28(%rbp), %rax
movl (%rdx), %edx
shll $0x10, %edx
addl %edx, %ecx
movl %ecx, %ecx
addq -0x10(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movl 0x86(%rax), %eax
andl $0x1f, %eax
shll $0x6, %eax
cltq
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ee8
movq -0x28(%rbp), %rdi
leaq 0x873e(%rip), %rsi      # 0x4b511
callq 0x15570
testb $0x1, %al
jne 0x42dde
jmp 0x42e2a
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28e73(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0x15, %eax
movl %eax, -0x50(%rbp)
addq $0x40, %rsi
leaq 0x28e57(%rip), %rdi     # 0x6bc60
callq 0x45690
movq %rax, %rcx
movl -0x50(%rbp), %eax
movl (%rcx), %ecx
shll $0xb, %ecx
addl %ecx, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ee6
movq -0x28(%rbp), %rdi
leaq 0x85b7(%rip), %rsi      # 0x4b3ec
callq 0x15570
testb $0x1, %al
jne 0x42e54
movq -0x28(%rbp), %rdi
leaq 0x85a7(%rip), %rsi      # 0x4b3f0
callq 0x15570
testb $0x1, %al
jne 0x42e54
jmp 0x42e9d
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28dfd(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0xb, %eax
movl %eax, -0x54(%rbp)
addq $0x40, %rsi
leaq 0x28de1(%rip), %rdi     # 0x6bc60
callq 0x45690
movq %rax, %rcx
movl -0x54(%rbp), %eax
movl (%rcx), %ecx
shll $0x15, %ecx
addl %ecx, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ee4
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28db4(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0x15, %eax
movl %eax, -0x58(%rbp)
addq $0x40, %rsi
leaq 0x28d98(%rip), %rdi     # 0x6bc60
callq 0x45690
movq %rax, %rcx
movl -0x58(%rbp), %eax
movl (%rcx), %ecx
shll $0x10, %ecx
addl %ecx, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ee6
jmp 0x42ee8
jmp 0x42ff9
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28d64(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
je 0x42f3b
movq -0x28(%rbp), %rsi
addq $0x40, %rsi
leaq 0x28d4a(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
je 0x42f3b
movq -0x28(%rbp), %rsi
addq $0x60, %rsi
leaq 0x28d30(%rip), %rdi     # 0x6bc60
callq 0x45630
cmpq $0x0, %rax
jne 0x42f8e
movl $0x10, %edi
callq 0x6210
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x60(%rbp)
leaq 0x85aa(%rip), %rsi      # 0x4b500
callq 0x6820
jmp 0x42f5d
movq -0x60(%rbp), %rdi
movq 0x28068(%rip), %rsi     # 0x6afd0
movq 0x28049(%rip), %rdx     # 0x6afb8
callq 0x6730
movq -0x60(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x18(%rbp)
movl %eax, -0x1c(%rbp)
callq 0x6350
jmp 0x431d0
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28cc3(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0xb, %eax
movl %eax, -0x68(%rbp)
addq $0x40, %rsi
leaq 0x28ca7(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movq %rax, %rcx
movl -0x68(%rbp), %eax
movl (%rcx), %ecx
shll $0x15, %ecx
addl %ecx, %eax
movl %eax, -0x64(%rbp)
addq $0x60, %rsi
leaq 0x28c83(%rip), %rdi     # 0x6bc60
callq 0x45690
movq %rax, %rcx
movl -0x64(%rbp), %eax
movl (%rcx), %ecx
shll $0x10, %ecx
addl %ecx, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x42ffb
movq -0x28(%rbp), %rsi
leaq 0x28c2a(%rip), %rdi     # 0x6bc30
callq 0x45690
movl (%rax), %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x431c6
movq -0x28(%rbp), %rsi
leaq 0x28a8b(%rip), %rdi     # 0x6bab0
callq 0x45690
movq %rax, %rcx
movq -0x28(%rbp), %rax
movl (%rcx), %ecx
shll $0x1a, %ecx
movl %ecx, %ecx
addq -0x10(%rbp), %rcx
movq %rcx, -0x10(%rbp)
cmpl $0x1, 0x80(%rax)
jne 0x430a9
movq -0x28(%rbp), %rdi
leaq 0x83b6(%rip), %rsi      # 0x4b40a
callq 0x15570
testb $0x1, %al
jne 0x4305f
jmp 0x43084
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28bf2(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0x10, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x430a7
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28bcd(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0x15, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x430a9
movq -0x28(%rbp), %rax
cmpl $0x2, 0x80(%rax)
jne 0x43174
movq -0x28(%rbp), %rdi
leaq 0x82bf(%rip), %rsi      # 0x4b384
callq 0x15570
testb $0x1, %al
jne 0x430e4
movq -0x28(%rbp), %rdi
leaq 0x82af(%rip), %rsi      # 0x4b388
callq 0x15570
testb $0x1, %al
jne 0x430e4
jmp 0x4312c
movq -0x28(%rbp), %rsi
addq $0x40, %rsi
leaq 0x28b6d(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0x10, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
addq $0x20, %rsi
leaq 0x28b4a(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0x15, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x43172
movq -0x28(%rbp), %rsi
addq $0x20, %rsi
leaq 0x28b25(%rip), %rdi     # 0x6bc60
callq 0x45690
movq -0x28(%rbp), %rsi
movl (%rax), %eax
shll $0x10, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
addq $0x40, %rsi
leaq 0x28b02(%rip), %rdi     # 0x6bc60
callq 0x45690
movl (%rax), %eax
shll $0x15, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x43174
movq -0x28(%rbp), %rax
movl 0x86(%rax), %eax
shrl $0x10, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x431c6
movq -0x28(%rbp), %rsi
leaq 0x28918(%rip), %rdi     # 0x6bab0
callq 0x45690
movq %rax, %rcx
movq -0x28(%rbp), %rax
movl (%rcx), %ecx
shll $0x1a, %ecx
movl %ecx, %ecx
addq -0x10(%rbp), %rcx
movq %rcx, -0x10(%rbp)
movl 0x86(%rax), %eax
shrl $0x10, %eax
movl %eax, %eax
addq -0x10(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
addq $0x70, %rsp
popq %rbp
retq
movq -0x18(%rbp), %rdi
callq 0x6790
nopl (%rax)