// File: /workspace/github_cpp_makefile_star2_O2/saumya-prakash[P]AssemblerEmulator/emu.cpp
// Function: main
int main(int argc, char** argv)
{
    cout<<unitbuf;
    cin.tie(&cout);

    if(argc==1)
    {
        cout<<"No input file specified"<<endl;
        return EXIT_FAILURE;
    }

    Emulator e1(argv[1]);

    int loading = e1.loader();

    if(loading)
        cout<<"Object file loaded successfully"<<endl<<endl;
    
    else
    {
        cout<<"Error in loading object file"<<endl;
        cout<<"Process terminated"<<endl;
        return EXIT_FAILURE;
    }

    print_options();
    cout<<endl;

    char c;     // interact with the user
    do
    {
        cin>>c;

        switch(c)
        {
            case 'a':       // execute all instructions in one go
                        if(e1.get_program_status()==-1)     // program in fault state
                        {
                            cout<<e1.get_fault_cause()<<endl<<endl;
                            break;
                        }

                        if(e1.get_program_status()==0)
                        {
                            cout<<"Program finished execution"<<endl<<endl;
                            break;
                        }
                        
                        while(e1.get_program_status()==1)
                            e1.execute();
                        
                        if(e1.get_program_status()==-1)     // program in fault state after completing execution
                        {
                            cout<<e1.get_fault_cause()<<endl<<endl;
                            break;
                        }

                        cout<<"Total instructions executed = "<<e1.instructions_executed()<<endl;
                        cout<<endl;
                        break;


            case 't':       // execute a single instruction with trace
                        if(e1.get_program_status()==-1)
                        {
                            cout<<e1.get_fault_cause()<<endl;
                            cout<<endl;
                            break;
                        }

                        if(e1.get_program_status()==0)
                        {   cout<<"Program finished execution"<<endl;
                            cout<<endl;
                            break;
                        }

                        cout<<e1.execute()<<endl;
                        cout<<endl;
                        break;

            case 's':   // execute all instrutions with trace
                        if(e1.get_program_status()==-1)     // program in fault state
                        {
                            cout<<e1.get_fault_cause()<<endl<<endl;
                            break;
                        }

                        if(e1.get_program_status()==0)
                        {
                            cout<<"Program finished execution"<<endl<<endl;
                            break;
                        }
                        

                        while(e1.get_program_status()==1)
                            cout<<e1.execute()<<endl;
                        cout<<endl;
                
                        cout<<"Total instructions executed = "<<e1.instructions_executed()<<endl;
                        cout<<endl;
                        break;


            case 'n':       // print specified number of instructions
                        {
                            int a = 0;
                            cin>>a;
                            int i = 0;
                            while(i<a && e1.get_program_status()==1)
                            {
                                i++;
                                cout<<e1.execute()<<endl;
                            }
                            cout<<endl;
                        }
                        
                        break;

            case 'q':       // show current architectural state
                        cout<<e1.current_state()<<endl;
                        cout<<endl;
                        break;
                        

            case 'u':       // disassemble
                        e1.disassemble(cout);
                        cout<<endl;
                        break;



            case 'd':       // outputs memory dump
                        e1.memory_dump(cout);
                        break; 


            case 'c':   // number of instructions executed thus far
                        cout<<"Number of instructions executed = "<<e1.instructions_executed()<<endl;
                        cout<<endl;
                        break;

            case 'x':       // QUIT
                        cout<<"Emulation terminated"<<endl;
                        cout<<endl;
                        break;

                        
            default:    cout<<"Invalid option"<<endl;
                        print_options();
                        cout<<endl;

                        continue;
                        break;
        }


    } while (c!='x');
    

    cout<<nounitbuf;
    return EXIT_SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq 0x601d(%rip), %rax      # 0x8fd0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
orl $0x2000, 0x18(%rax,%rcx) # imm = 0x2000
movq 0x6017(%rip), %rcx      # 0x8fe0
movq (%rcx), %rdx
movq -0x18(%rdx), %rdx
movq %rax, 0xd8(%rcx,%rdx)
cmpl $0x1, %edi
jne 0x3000
movq 0x5fec(%rip), %rdi      # 0x8fd0
leaq 0x3198(%rip), %rsi      # 0x6183
callq 0x2180
movq %rax, %rdi
callq 0x20d0
pushq $0x1
popq %rbx
jmp 0x343a
movq 0x8(%rsi), %rsi
leaq 0x10(%rsp), %rdi
leaq 0xc(%rsp), %rdx
callq 0x34b0
leaq 0x30(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x34ec
leaq 0x10(%rsp), %rdi
callq 0x20c0
leaq 0x30(%rsp), %rdi
callq 0x3608
testb %al, %al
je 0x33dd
movq 0x5f8b(%rip), %rdi      # 0x8fd0
leaq 0x314f(%rip), %rsi      # 0x619b
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
callq 0x20d0
callq 0x2eac
movq 0x5f63(%rip), %rbx      # 0x8fd0
movq %rbx, %rdi
callq 0x20d0
leaq 0x30(%rsp), %r13
leaq 0x10(%rsp), %rbp
leaq 0xa8(%rsp), %r14
leaq 0x2f76(%rip), %r12      # 0x6004
movq 0x5f4b(%rip), %rdi      # 0x8fe0
leaq 0xb(%rsp), %rsi
callq 0x2210
movzbl 0xb(%rsp), %eax
leal -0x6e(%rax), %ecx
cmpl $0xa, %ecx
ja 0x311c
movslq (%r12,%rcx,4), %rax
addq %r12, %rax
leaq 0x318e(%rip), %rsi      # 0x6248
jmpq *%rax
andl $0x0, 0xc(%rsp)
movq 0x5f18(%rip), %rdi      # 0x8fe0
leaq 0xc(%rsp), %rsi
callq 0x20f0
xorl %r15d, %r15d
cmpl 0xc(%rsp), %r15d
jge 0x3252
movq %r13, %rdi
callq 0x4314
cmpl $0x1, %eax
jne 0x3252
movq %rbp, %rdi
movq %r13, %rsi
callq 0x38be
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rbp, %rdi
callq 0x20c0
incl %r15d
jmp 0x30d5
cmpl $0x61, %eax
je 0x325f
leaq 0x30f9(%rip), %rsi      # 0x6225
cmpl $0x63, %eax
je 0x3346
cmpl $0x64, %eax
jne 0x314a
movq %r13, %rdi
movq %rbx, %rsi
callq 0x456e
jmp 0x336b
movq %rbx, %rdi
leaq 0x3109(%rip), %rsi      # 0x625d
callq 0x2180
movq %rax, %rdi
callq 0x20d0
callq 0x2eac
movq %rbx, %rdi
jmp 0x3366
movq %r13, %rdi
callq 0x4314
cmpl $-0x1, %eax
je 0x32d2
movq %r13, %rdi
callq 0x4314
leaq 0x305d(%rip), %rsi      # 0x61eb
testl %eax, %eax
je 0x31b5
movq %rbp, %rdi
movq %r13, %rsi
callq 0x38be
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
jmp 0x32f5
movq %rbx, %rdi
callq 0x2180
jmp 0x335b
movq %r13, %rdi
callq 0x4314
cmpl $-0x1, %eax
je 0x3302
movq %r13, %rdi
callq 0x4314
testl %eax, %eax
je 0x32a2
movq %r13, %rdi
callq 0x4314
cmpl $0x1, %eax
jne 0x32c1
movq %rbp, %rdi
movq %r13, %rsi
callq 0x38be
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rbp, %rdi
callq 0x20c0
jmp 0x31e3
movq %rbp, %rdi
movq %r13, %rsi
callq 0x3da4
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
jmp 0x32f5
movq %r13, %rdi
movq %rbx, %rsi
callq 0x43fc
movq %rbx, %rdi
jmp 0x3366
movq %rbx, %rdi
callq 0x20d0
jmp 0x336b
movq %r13, %rdi
callq 0x4314
cmpl $-0x1, %eax
je 0x337b
movq %r13, %rdi
callq 0x4314
testl %eax, %eax
je 0x32a2
movq %r13, %rdi
callq 0x4314
cmpl $0x1, %eax
jne 0x3332
movq %r14, %rdi
movq %r13, %rsi
callq 0x38be
movq %r14, %rdi
callq 0x20c0
jmp 0x327c
movq %rbx, %rdi
leaq 0x2f3f(%rip), %rsi      # 0x61eb
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
jmp 0x3366
movq %rbx, %rdi
callq 0x20d0
leaq 0x2f36(%rip), %rsi      # 0x6206
jmp 0x3346
movq %rbp, %rdi
leaq 0x88(%rsp), %rsi
callq 0x2230
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rbp, %rdi
callq 0x20c0
movq %rbx, %rdi
jmp 0x3366
movq %rbp, %rdi
leaq 0x88(%rsp), %rsi
callq 0x2230
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
callq 0x20d0
jmp 0x33d3
movq %r13, %rdi
callq 0x4314
leaq 0x2ec5(%rip), %rsi      # 0x6206
cmpl $-0x1, %eax
je 0x33a8
movq %rbx, %rdi
callq 0x2180
movq 0x70(%rsp), %rsi
movq %rax, %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x20d0
cmpb $0x78, 0xb(%rsp)
jne 0x308e
jmp 0x3418
movq %rbp, %rdi
leaq 0x88(%rsp), %rsi
callq 0x2230
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
callq 0x20d0
jmp 0x33d3
movq %rbp, %rdi
leaq 0x88(%rsp), %rsi
callq 0x2230
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x2170
movq %rax, %rdi
callq 0x20d0
movq %rax, %rdi
callq 0x20d0
movq %rbp, %rdi
callq 0x20c0
jmp 0x336b
movq 0x5bec(%rip), %rdi      # 0x8fd0
leaq 0x2dd0(%rip), %rsi      # 0x61bb
callq 0x2180
movq %rax, %rdi
callq 0x20d0
movq 0x5bd1(%rip), %rdi      # 0x8fd0
leaq 0x2dd2(%rip), %rsi      # 0x61d8
callq 0x2180
movq %rax, %rdi
callq 0x20d0
pushq $0x1
popq %rbx
jmp 0x3430
movq 0x5bb1(%rip), %rax      # 0x8fd0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
andl $0xffffdfff, 0x18(%rax,%rcx) # imm = 0xFFFFDFFF
xorl %ebx, %ebx
leaq 0x30(%rsp), %rdi
callq 0x354a
movl %ebx, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x348c
jmp 0x349b
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x20c0
jmp 0x34a8
movq %rax, %rbx
jmp 0x34a8
jmp 0x348c
jmp 0x348c
jmp 0x348c
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x348c
jmp 0x348c
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x349b
jmp 0x348c
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x20c0
jmp 0x349e
movq %rax, %rbx
leaq 0x30(%rsp), %rdi
callq 0x354a
movq %rbx, %rdi
callq 0x22b0